public ConfigurationRecognizer(PropertyInfo unrecognizedProperty) { _unrecognizedProperty = unrecognizedProperty ?? throw new ArgumentNullException(nameof(unrecognizedProperty)); _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)); } }
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 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); }
protected virtual object CreateInstance(Type type) { if (type.IsArray) { if (type.GetArrayRank() > 1) { throw new InvalidOperationException(string.Format(Properties.Resources.Error_UnsupportedMultidimensionalArray, type)); } return(Array.CreateInstance(type.GetElementType(), 0)); } if (type.IsInterface) { var contract = ConfigurationUtility.GetImplementedContract(type, typeof(IReadOnlyDictionary <,>), typeof(IDictionary <,>)); if (contract != null) { var dictionaryType = typeof(Dictionary <,>).MakeGenericType(contract.GenericTypeArguments[0], contract.GenericTypeArguments[1]); return(dictionaryType.GenericTypeArguments[0] != typeof(string) ? Activator.CreateInstance(dictionaryType) : Activator.CreateInstance(dictionaryType, new object[] { StringComparer.OrdinalIgnoreCase })); } contract = ConfigurationUtility.GetImplementedContract(type, typeof(ISet <>)); if (contract != null) { var setType = typeof(HashSet <>).MakeGenericType(contract.GenericTypeArguments[0]); return(Activator.CreateInstance(setType)); } contract = ConfigurationUtility.GetImplementedContract(type, typeof(IReadOnlyList <>), typeof(IList <>), typeof(IReadOnlyCollection <>), typeof(ICollection <>), typeof(IEnumerable <>)); if (contract != null) { var listType = typeof(List <>).MakeGenericType(contract.GenericTypeArguments[0]); return(Activator.CreateInstance(listType)); } } try { if (type.IsInterface || type.IsAbstract) { return(Zongsoft.Data.Model.Build(type)); } return(Activator.CreateInstance(type)); } catch (Exception ex) { throw new InvalidOperationException(string.Format(Properties.Resources.Error_FailedToActivate, type), ex); } }
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 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); } } } }