From ea9425c9abd6e27f0d09be2073ef4b1679d5bd1f Mon Sep 17 00:00:00 2001 From: Kieranties Date: Mon, 14 Dec 2015 11:46:58 +0000 Subject: [PATCH] Enable binding of IConfiguration/IConfigurationSection --- .../ConfigurationBinder.cs | 7 ++ .../ConfigurationBinderTests.cs | 81 +++++++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/src/Microsoft.Extensions.Configuration.Binder/ConfigurationBinder.cs b/src/Microsoft.Extensions.Configuration.Binder/ConfigurationBinder.cs index 0d8378db..cdeb04f3 100644 --- a/src/Microsoft.Extensions.Configuration.Binder/ConfigurationBinder.cs +++ b/src/Microsoft.Extensions.Configuration.Binder/ConfigurationBinder.cs @@ -82,6 +82,7 @@ private static void BindProperty(PropertyInfo property, object instance, IConfig } propertyValue = BindInstance(property.PropertyType, propertyValue, config.GetSection(property.Name)); + if (propertyValue != null && hasPublicSetter) { property.SetValue(instance, propertyValue); @@ -90,6 +91,12 @@ private static void BindProperty(PropertyInfo property, object instance, IConfig private static object BindInstance(Type type, object instance, IConfiguration config) { + // if binding IConfigurationSection, break early + if (type == typeof(IConfigurationSection)) + { + return config; + } + var section = config as IConfigurationSection; var configValue = section?.Value; if (configValue != null) diff --git a/test/Microsoft.Extensions.Configuration.Binder.Test/ConfigurationBinderTests.cs b/test/Microsoft.Extensions.Configuration.Binder.Test/ConfigurationBinderTests.cs index 5f82301e..64d03d59 100644 --- a/test/Microsoft.Extensions.Configuration.Binder.Test/ConfigurationBinderTests.cs +++ b/test/Microsoft.Extensions.Configuration.Binder.Test/ConfigurationBinderTests.cs @@ -6,6 +6,7 @@ using System.ComponentModel; using System.Reflection; using Microsoft.Extensions.Configuration.Memory; +using Microsoft.Extensions.Primitives; using Xunit; namespace Microsoft.Extensions.Configuration.Binder.Test @@ -73,6 +74,86 @@ public class GenericOptions public T Value { get; set; } } + public class ConfigurationInterfaceOptions + { + public IConfigurationSection Section { get; set; } + } + + public class DerivedOptionsWithIConfigurationSection : DerivedOptions + { + public IConfigurationSection DerivedSection { get; set; } + } + + [Fact] + public void CanBindIConfigurationSection() + { + var dic = new Dictionary + { + {"Section:Integer", "-2"}, + {"Section:Boolean", "TRUe"}, + {"Section:Nested:Integer", "11"}, + {"Section:Virtual", "Sup"} + }; + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddInMemoryCollection(dic); + var config = configurationBuilder.Build(); + + var options = new ConfigurationInterfaceOptions(); + config.Bind(options); + + var childOptions = new DerivedOptions(); + options.Section.Bind(childOptions); + + Assert.True(childOptions.Boolean); + Assert.Equal(-2, childOptions.Integer); + Assert.Equal(11, childOptions.Nested.Integer); + Assert.Equal("Derived:Sup", childOptions.Virtual); + + Assert.Equal("Section", options.Section.Key); + Assert.Equal("Section", options.Section.Path); + Assert.Equal(null, options.Section.Value); + } + + [Fact] + public void CanBindIConfigurationSectionWithDerivedOptionsSection() + { + var dic = new Dictionary + { + {"Section:Integer", "-2"}, + {"Section:Boolean", "TRUe"}, + {"Section:Nested:Integer", "11"}, + {"Section:Virtual", "Sup"}, + {"Section:DerivedSection:Nested:Integer", "11"}, + {"Section:DerivedSection:Virtual", "Sup"} + }; + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddInMemoryCollection(dic); + var config = configurationBuilder.Build(); + + var options = new ConfigurationInterfaceOptions(); + config.Bind(options); + + var childOptions = new DerivedOptionsWithIConfigurationSection(); + options.Section.Bind(childOptions); + + + var childDerivedOptions = new DerivedOptions(); + childOptions.DerivedSection.Bind(childDerivedOptions); + + Assert.True(childOptions.Boolean); + Assert.Equal(-2, childOptions.Integer); + Assert.Equal(11, childOptions.Nested.Integer); + Assert.Equal("Derived:Sup", childOptions.Virtual); + Assert.Equal(11, childDerivedOptions.Nested.Integer); + Assert.Equal("Derived:Sup", childDerivedOptions.Virtual); + + Assert.Equal("Section", options.Section.Key); + Assert.Equal("Section", options.Section.Path); + Assert.Equal("DerivedSection", childOptions.DerivedSection.Key); + Assert.Equal("Section:DerivedSection", childOptions.DerivedSection.Path); + Assert.Equal(null, options.Section.Value); + } + [Fact] public void GetScalarNullable() {