public object Resolve(Type type, IConfiguration configuration, ConfigurationBinderOptions options)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            var instance = this.CreateInstance(type);

            this.Resolve(instance, configuration, options);
            return(instance);
        }
        private void ResolveInstance(object instance, IConfiguration configuration, ConfigurationBinderOptions options)
        {
            if (configuration is IConfigurationSection section)
            {
                var properties = this.GetProperties(instance.GetType().GetTypeInfo());

                if (section.Value != null)
                {
                    if (properties.TryGetValue(section.Key, out var property))
                    {
                        if (SetPathInfo(instance, property, section))
                        {
                            return;
                        }

                        if (property.SetValue(instance, section.Value))
                        {
                            return;
                        }

                        throw new InvalidOperationException(string.Format(Properties.Resources.Error_FailedBinding, section.Path, property.PropertyType));
                    }

                    this.OnUnrecognize(instance, properties, section, options);
                }
                else
                {
                    if (properties.TryGetValue(section.Key, out var property))
                    {
                        var target = property.GetValue(instance);

                        if (target == null)
                        {
                            target = this.Resolve(property.PropertyType, configuration, options);
                        }
                        else
                        {
                            this.Resolve(target, configuration, options);
                        }

                        property.SetValue(instance, target);
                    }
                    else
                    {
                        if (!this.ResolveCollection(instance, section, properties, options))
                        {
                            this.OnUnrecognize(instance, properties, section, options);
                        }
                    }
                }
            }
        }
        public static void Bind(this IConfiguration configuration, object instance, Action <ConfigurationBinderOptions> configureOptions)
        {
            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            if (instance != null)
            {
                var options = new ConfigurationBinderOptions();
                configureOptions?.Invoke(options);
                GetResolver(instance.GetType()).Resolve(instance, configuration, options);
            }
        }
        public void Resolve(object instance, IConfiguration configuration, ConfigurationBinderOptions options)
        {
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }

            var type = instance.GetType();

            if (type == typeof(IConfigurationSection))
            {
                return;
            }

            foreach (var child in configuration.GetChildren())
            {
                this.ResolveInstance(instance, child, options);
            }
        }
Example #5
0
        public bool Recognize(object target, IConfigurationSection configuration, ConfigurationBinderOptions options)
        {
            if (target == null)
            {
                return(false);
            }

            var unrecognizedProperty = _unrecognizedProperty;
            var dictionary           = Reflection.Reflector.GetValue(unrecognizedProperty, ref target);

            if (dictionary == null)
            {
                if (!unrecognizedProperty.CanWrite)
                {
                    throw new ConfigurationException($"The {unrecognizedProperty.Name} unrecognized property value is null and it is read-only.");
                }

                if (unrecognizedProperty.PropertyType.IsAbstract)
                {
                    var dictionaryType = ConfigurationUtility.GetImplementedContract(unrecognizedProperty.PropertyType, typeof(IDictionary <,>))?.GetTypeInfo();

                    if (dictionaryType == null || dictionaryType.GenericTypeArguments[0] != typeof(string))
                    {
                        throw new InvalidOperationException(string.Format(Properties.Resources.Error_InvalidUnrecognizedProperty, unrecognizedProperty.Name));
                    }

                    dictionary = Activator.CreateInstance(typeof(Dictionary <,>).MakeGenericType(typeof(string), dictionaryType.GenericTypeArguments[1]), new object[] { StringComparer.OrdinalIgnoreCase });
                }
                else
                {
                    dictionary = Activator.CreateInstance(unrecognizedProperty.PropertyType);
                }

                Reflection.Reflector.SetValue(unrecognizedProperty, ref target, dictionary);
            }

            this.SetDictionaryValue(dictionary, configuration);

            return(true);
        }
        private bool ResolveDefaultProperty(object instance, PropertyToken property, IDictionary <string, PropertyToken> properties, IConfigurationSection configuration, ConfigurationBinderOptions options)
        {
            if (property == null)
            {
                return(false);
            }

            var value = property.GetValue(instance);

            if (value == null)
            {
                if (!property.CanWrite)
                {
                    return(false);
                }

                value = this.CreateInstance(property.PropertyType);

                if (!property.SetValue(instance, value))
                {
                    throw new ConfigurationException($"The default collection property {property.Name} of '{instance.GetType().FullName}' type is null and it cannot be set.");
                }
            }

            return(this.ResolveCollection(value, configuration, this.GetProperties(value.GetType().GetTypeInfo()), options));
        }
        protected virtual void OnUnrecognize(object target, IDictionary <string, PropertyToken> properties, IConfigurationSection configuration, ConfigurationBinderOptions options)
        {
            var unrecognizedProperty = ConfigurationRecognizerProvider.GetUnrecognizedProperty(target.GetType());

            if (unrecognizedProperty == null)
            {
                if (configuration.Value == null && this.ResolveDefaultProperty(target, FindDefaultProperty(properties.Values), properties, configuration, options))
                {
                    return;
                }

                if (options !.UnrecognizedError)
                {
                    throw new ConfigurationException($"The specified '{configuration.Path}' configuration section cannot be bound to a member of the '{target.GetType()}' type.");
                }

                return;
            }

            if (configuration.Value == null)
            {
                var attribute = unrecognizedProperty.GetCustomAttribute <ConfigurationPropertyAttribute>(true);

                //如果指定的未识别属性名被注解为空或星号,则表示它是一个默认集合属性
                if (attribute != null && (string.IsNullOrEmpty(attribute.Name) || attribute.Name == "*"))
                {
                    //解析默认集合成功则返回,否则抛出异常
                    if (this.ResolveDefaultProperty(target, properties[unrecognizedProperty.Name], properties, configuration, options))
                    {
                        return;
                    }

                    throw new ConfigurationException($"The {unrecognizedProperty.Name} property of type '{target.GetType().FullName}' is annotated as the default collection, but the binding for this property fails.");
                }
            }

            var recognizers = this.Recognizers ?? ConfigurationRecognizerProvider.Default;
            var recognizer  = recognizers.GetRecognize(target.GetType()) ??
                              throw new ConfigurationException($"Unable to get a recognizer of type '{target.GetType().FullName}'.");

            if (!recognizer.Recognize(target, configuration, options) && options !.UnrecognizedError)
            {
                throw new ConfigurationException($"The '{configuration.Path}' configuration section is not recognized.");
            }
        }
        public void Attach(object instance, IConfiguration configuration, ConfigurationBinderOptions options)
        {
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }

            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            var properties = this.GetProperties(instance.GetType().GetTypeInfo()).Values.Distinct().ToArray();

            foreach (var property in properties)
            {
                if (Common.TypeExtension.IsScalarType(property.PropertyType))
                {
                    configuration[property.ConfigurationKey] = property.GetStringValue(instance);
                    continue;
                }

                var propertyValue = property.GetValue(instance);

                var dictionaryType = ConfigurationUtility.GetImplementedContract(
                    property.PropertyType,
                    typeof(IReadOnlyDictionary <,>),
                    typeof(IDictionary <,>));

                if (dictionaryType != null)
                {
                    //if(propertyValue.GetType() != dictionaryType)
                    //	this.Attach(propertyValue, configuration.GetSection(property.ConfigurationKey), options);

                    foreach (DictionaryEntry entry in (IEnumerable)propertyValue)
                    {
                        var key = ConfigurationPath.Combine(property.ConfigurationKey, entry.Key.ToString());
                        this.Attach(entry.Value, configuration.GetSection(key), options);
                    }

                    continue;
                }

                var collectionType = ConfigurationUtility.GetImplementedContract(
                    property.PropertyType,
                    typeof(IReadOnlyCollection <>),
                    typeof(ICollection <>),
                    typeof(IEnumerable <>));

                if (collectionType != null)
                {
                    //if(propertyValue.GetType() != collectionType)
                    //	this.Attach(propertyValue, configuration.GetSection(property.ConfigurationKey), options);

                    int index = 0;

                    foreach (var entry in (IEnumerable)propertyValue)
                    {
                        var key = ConfigurationPath.Combine(property.ConfigurationKey, index++.ToString());
                        this.Attach(entry, configuration.GetSection(key), options);
                    }

                    continue;
                }

                this.Attach(propertyValue, configuration.GetSection(property.ConfigurationKey), options);
            }
        }
        private bool ResolveCollection(object instance, IConfigurationSection configuration, IDictionary <string, PropertyToken> properties, ConfigurationBinderOptions options)
        {
            var dictionaryType = ConfigurationUtility.GetImplementedContract(instance.GetType(), typeof(IDictionary <,>));

            if (dictionaryType != null)
            {
                object key = configuration.Key;

                //如果字典键类型不是字符串并且配置键文本转换失败则抛出异常
                if (dictionaryType.GenericTypeArguments[0] != typeof(string) && !Common.Convert.TryConvertValue(key, dictionaryType.GenericTypeArguments[0], out key))
                {
                    throw new ConfigurationException($"Unable to convert the ‘{key}’ configuration key to a dictionary key type of ‘{dictionaryType.GenericTypeArguments[0].FullName}’ type.");
                }

                var valueType = dictionaryType.GenericTypeArguments[1];
                var setter    = dictionaryType.GetTypeInfo().GetDeclaredProperty("Item");

                Reflection.Reflector.SetValue(setter, ref instance, this.Resolve(valueType, configuration, options), new object[] { key });

                return(true);
            }

            var collectionType = ConfigurationUtility.GetImplementedContract(instance.GetType(), typeof(ICollection <>));

            if (collectionType != null)
            {
                var valueType = collectionType.GenericTypeArguments[0];
                var add       = collectionType.GetTypeInfo().GetDeclaredMethod("Add");

                add.Invoke(instance, new object[] { this.Resolve(valueType, configuration, options) });

                return(true);
            }

            //返回失败
            return(false);
        }
        private void ResolveInstance(object instance, IConfiguration configuration, ConfigurationBinderOptions options)
        {
            if (configuration is IConfigurationSection section)
            {
                var properties = this.GetProperties(instance.GetType().GetTypeInfo());

                if (section.Value != null)
                {
                    if (properties.TryGetValue(section.Key, out var property))
                    {
                        if (property.SetValue(instance, section.Value))
                        {
                            return;
                        }

                        throw new InvalidOperationException(string.Format(Properties.Resources.Error_FailedBinding, section.Path, instance.GetType()));
                    }

                    this.OnUnrecognize(instance, section.Key, section.Value);
                }
                else
                {
                    if (properties.TryGetValue(section.Key, out var property))
                    {
                        var target = property.GetValue(instance);

                        if (target == null)
                        {
                            target = this.Resolve(property.PropertyType, configuration, options);
                        }
                        else
                        {
                            this.Resolve(target, configuration, options);
                        }

                        property.SetValue(instance, target);
                    }
                    else
                    {
                        var dictionaryType = ConfigurationUtility.GetImplementedContract(instance.GetType(), typeof(IDictionary <,>));

                        if (dictionaryType != null)
                        {
                            if (dictionaryType.GenericTypeArguments[0] != typeof(string))
                            {
                                return;
                            }

                            var valueType = dictionaryType.GenericTypeArguments[1];
                            var setter    = dictionaryType.GetTypeInfo().GetDeclaredProperty("Item");

                            Reflection.Reflector.SetValue(setter, ref instance, this.Resolve(valueType, configuration, options), new object[] { section.Key });

                            return;
                        }

                        var collectionType = ConfigurationUtility.GetImplementedContract(instance.GetType(), typeof(ICollection <>));

                        if (collectionType != null)
                        {
                            var valueType = collectionType.GenericTypeArguments[0];
                            var add       = collectionType.GetTypeInfo().GetDeclaredMethod("Add");

                            add.Invoke(instance, new object[] { this.Resolve(valueType, configuration, options) });

                            return;
                        }

                        this.OnUnrecognize(instance, configuration);
                    }
                }
            }
        }