using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using FxResources.Microsoft.Extensions.Configuration.Binder; using Microsoft.CodeAnalysis; using Microsoft.Extensions.Internal; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.Binder.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyMetadata("Serviceable", "True")] [assembly: AssemblyMetadata("PreferInbox", "True")] [assembly: AssemblyDefaultAlias("Microsoft.Extensions.Configuration.Binder")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: CLSCompliant(true)] [assembly: AssemblyMetadata("IsTrimmable", "True")] [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.System32 | DllImportSearchPath.AssemblyDirectory)] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] [assembly: AssemblyDescription("Provides the functionality to bind an object to data in configuration providers for Microsoft.Extensions.Configuration. This package enables you to represent the configuration data as strongly-typed classes defined in the application code. To bind a configuration, use the Microsoft.Extensions.Configuration.ConfigurationBinder.Get extension method on the IConfiguration object. To use this package, you also need to install a package for the configuration provider, for example, Microsoft.Extensions.Configuration.Json for the JSON provider.")] [assembly: AssemblyFileVersion("9.0.24.52809")] [assembly: AssemblyInformationalVersion("9.0.0+9d5a6a9aa463d6d10b0b0ba6d5982cc82f363dc3")] [assembly: AssemblyProduct("Microsoft® .NET")] [assembly: AssemblyTitle("Microsoft.Extensions.Configuration.Binder")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/dotnet/runtime")] [assembly: AssemblyVersion("9.0.0.0")] [module: RefSafetyRules(11)] [module: System.Runtime.CompilerServices.NullablePublicOnly(true)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class NullablePublicOnlyAttribute : Attribute { public readonly bool IncludesInternals; public NullablePublicOnlyAttribute(bool P_0) { IncludesInternals = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace FxResources.Microsoft.Extensions.Configuration.Binder { internal static class SR { } } namespace System { internal static class ThrowHelper { internal static void ThrowIfNull(object? argument, [CallerArgumentExpression("argument")] string? paramName = null) { if (argument == null) { Throw(paramName); } } private static void Throw(string paramName) { throw new ArgumentNullException(paramName); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string IfNullOrWhitespace(string? argument, [CallerArgumentExpression("argument")] string paramName = "") { if (argument == null) { throw new ArgumentNullException(paramName); } if (string.IsNullOrWhiteSpace(argument)) { if (argument == null) { throw new ArgumentNullException(paramName); } throw new ArgumentException(paramName, "Argument is whitespace"); } return argument; } } internal static class SR { private static readonly bool s_usingResourceKeys = GetUsingResourceKeysSwitchValue(); private static ResourceManager s_resourceManager; internal static ResourceManager ResourceManager => s_resourceManager ?? (s_resourceManager = new ResourceManager(typeof(SR))); internal static string Error_CannotActivateAbstractOrInterface => GetResourceString("Error_CannotActivateAbstractOrInterface"); internal static string Error_CannotBindToConstructorParameter => GetResourceString("Error_CannotBindToConstructorParameter"); internal static string Error_ConstructorParametersDoNotMatchProperties => GetResourceString("Error_ConstructorParametersDoNotMatchProperties"); internal static string Error_FailedBinding => GetResourceString("Error_FailedBinding"); internal static string Error_FailedToActivate => GetResourceString("Error_FailedToActivate"); internal static string Error_GeneralErrorWhenBinding => GetResourceString("Error_GeneralErrorWhenBinding"); internal static string Error_MissingConfig => GetResourceString("Error_MissingConfig"); internal static string Error_MissingPublicInstanceConstructor => GetResourceString("Error_MissingPublicInstanceConstructor"); internal static string Error_MultipleParameterizedConstructors => GetResourceString("Error_MultipleParameterizedConstructors"); internal static string Error_ParameterBeingBoundToIsUnnamed => GetResourceString("Error_ParameterBeingBoundToIsUnnamed"); internal static string Error_ParameterHasNoMatchingConfig => GetResourceString("Error_ParameterHasNoMatchingConfig"); internal static string Error_UnsupportedMultidimensionalArray => GetResourceString("Error_UnsupportedMultidimensionalArray"); private static bool GetUsingResourceKeysSwitchValue() { if (!AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out var isEnabled)) { return false; } return isEnabled; } internal static bool UsingResourceKeys() { return s_usingResourceKeys; } private static string GetResourceString(string resourceKey) { if (UsingResourceKeys()) { return resourceKey; } string result = null; try { result = ResourceManager.GetString(resourceKey); } catch (MissingManifestResourceException) { } return result; } private static string GetResourceString(string resourceKey, string defaultString) { string resourceString = GetResourceString(resourceKey); if (!(resourceKey == resourceString) && resourceString != null) { return resourceString; } return defaultString; } internal static string Format(string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(resourceFormat, p1); } internal static string Format(string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(resourceFormat, p1, p2); } internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(resourceFormat, p1, p2, p3); } internal static string Format(string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(resourceFormat, args); } return resourceFormat; } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1); } return string.Format(provider, resourceFormat, p1); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2); } return string.Format(provider, resourceFormat, p1, p2); } internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3) { if (UsingResourceKeys()) { return string.Join(", ", resourceFormat, p1, p2, p3); } return string.Format(provider, resourceFormat, p1, p2, p3); } internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) { if (args != null) { if (UsingResourceKeys()) { return resourceFormat + ", " + string.Join(", ", args); } return string.Format(provider, resourceFormat, args); } return resourceFormat; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)] internal sealed class DynamicallyAccessedMembersAttribute : Attribute { public DynamicallyAccessedMemberTypes MemberTypes { get; } public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) { MemberTypes = memberTypes; } } [Flags] internal enum DynamicallyAccessedMemberTypes { None = 0, PublicParameterlessConstructor = 1, PublicConstructors = 3, NonPublicConstructors = 4, PublicMethods = 8, NonPublicMethods = 0x10, PublicFields = 0x20, NonPublicFields = 0x40, PublicNestedTypes = 0x80, NonPublicNestedTypes = 0x100, PublicProperties = 0x200, NonPublicProperties = 0x400, PublicEvents = 0x800, NonPublicEvents = 0x1000, Interfaces = 0x2000, All = -1 } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresDynamicCodeAttribute : Attribute { public string Message { get; } public string? Url { get; set; } public RequiresDynamicCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresUnreferencedCodeAttribute : Attribute { public string Message { get; } public string? Url { get; set; } public RequiresUnreferencedCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] internal sealed class UnconditionalSuppressMessageAttribute : Attribute { public string Category { get; } public string CheckId { get; } public string? Scope { get; set; } public string? Target { get; set; } public string? MessageId { get; set; } public string? Justification { get; set; } public UnconditionalSuppressMessageAttribute(string category, string checkId) { Category = category; CheckId = checkId; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class DisallowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class MaybeNullWhenAttribute : Attribute { public bool ReturnValue { get; } public MaybeNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] internal sealed class NotNullIfNotNullAttribute : Attribute { public string ParameterName { get; } public NotNullIfNotNullAttribute(string parameterName) { ParameterName = parameterName; } } [AttributeUsage(AttributeTargets.Method, Inherited = false)] internal sealed class DoesNotReturnAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullAttribute : Attribute { public string[] Members { get; } public MemberNotNullAttribute(string member) { Members = new string[1] { member }; } public MemberNotNullAttribute(params string[] members) { Members = members; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } } namespace System.Runtime.InteropServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] internal sealed class LibraryImportAttribute : Attribute { public string LibraryName { get; } public string? EntryPoint { get; set; } public StringMarshalling StringMarshalling { get; set; } public Type? StringMarshallingCustomType { get; set; } public bool SetLastError { get; set; } public LibraryImportAttribute(string libraryName) { LibraryName = libraryName; } } internal enum StringMarshalling { Custom, Utf8, Utf16 } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] internal sealed class CallerArgumentExpressionAttribute : Attribute { public string ParameterName { get; } public CallerArgumentExpressionAttribute(string parameterName) { ParameterName = parameterName; } } } namespace Microsoft.Extensions.Internal { internal static class ParameterDefaultValue { public static bool TryGetDefaultValue(ParameterInfo parameter, out object? defaultValue) { bool tryToGetDefaultValue; bool num = CheckHasDefaultValue(parameter, out tryToGetDefaultValue); defaultValue = null; if (num) { if (tryToGetDefaultValue) { defaultValue = parameter.DefaultValue; } bool flag = parameter.ParameterType.IsGenericType && parameter.ParameterType.GetGenericTypeDefinition() == typeof(Nullable<>); if (defaultValue == null && parameter.ParameterType.IsValueType && !flag) { defaultValue = CreateValueType(parameter.ParameterType); } if (defaultValue != null && flag) { Type underlyingType = Nullable.GetUnderlyingType(parameter.ParameterType); if (underlyingType != null && underlyingType.IsEnum) { defaultValue = Enum.ToObject(underlyingType, defaultValue); } } } return num; [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", Justification = "CreateValueType is only called on a ValueType. You can always create an instance of a ValueType.")] static object? CreateValueType(Type t) { return FormatterServices.GetUninitializedObject(t); } } public static bool CheckHasDefaultValue(ParameterInfo parameter, out bool tryToGetDefaultValue) { tryToGetDefaultValue = true; try { return parameter.HasDefaultValue; } catch (FormatException) when (parameter.ParameterType == typeof(DateTime)) { tryToGetDefaultValue = false; return true; } } } } namespace Microsoft.Extensions.Configuration { public class BinderOptions { public bool BindNonPublicProperties { get; set; } public bool ErrorOnUnknownConfiguration { get; set; } } internal sealed class BindingPoint { private readonly Func _initialValueProvider; private object _initialValue; private object _setValue; private bool _valueSet; public bool IsReadOnly { get; } public bool HasNewValue { get { if (IsReadOnly) { return false; } if (_valueSet) { return true; } Type type = _initialValue?.GetType(); if ((object)type != null && type.IsValueType) { return !type.IsPrimitive; } return false; } } public object? Value { get { object obj; if (!_valueSet) { obj = _initialValue; if (obj == null) { return _initialValue = _initialValueProvider?.Invoke(); } } else { obj = _setValue; } return obj; } } public BindingPoint(object? initialValue = null, bool isReadOnly = false) { _initialValue = initialValue; IsReadOnly = isReadOnly; } public BindingPoint(Func initialValueProvider, bool isReadOnly) { _initialValueProvider = initialValueProvider; IsReadOnly = isReadOnly; } public void SetValue(object? newValue) { _setValue = newValue; _valueSet = true; } public void TrySetValue(object? newValue) { if (!IsReadOnly) { SetValue(newValue); } } } public static class ConfigurationBinder { private const BindingFlags DeclaredOnlyLookup = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; private const string DynamicCodeWarningMessage = "Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types."; private const string TrimmingWarningMessage = "In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed."; private const string InstanceGetTypeTrimmingWarningMessage = "Cannot statically analyze the type of instance so its members may be trimmed"; private const string PropertyTrimmingWarningMessage = "Cannot statically analyze property.PropertyType so its members may be trimmed."; [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static T? Get<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration) { return configuration.Get(null); } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static T? Get<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration, Action? configureOptions) { System.ThrowHelper.ThrowIfNull(configuration, "configuration"); object obj = configuration.Get(typeof(T), configureOptions); if (obj == null) { return default(T); } return (T)obj; } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static object? Get(this IConfiguration configuration, Type type) { return configuration.Get(type, null); } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static object? Get(this IConfiguration configuration, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, Action? configureOptions) { System.ThrowHelper.ThrowIfNull(configuration, "configuration"); System.ThrowHelper.ThrowIfNull(type, "type"); BinderOptions binderOptions = new BinderOptions(); configureOptions?.Invoke(binderOptions); BindingPoint bindingPoint = new BindingPoint(); BindInstance(type, bindingPoint, configuration, binderOptions, isParentCollection: false); return bindingPoint.Value; } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze the type of instance so its members may be trimmed")] public static void Bind(this IConfiguration configuration, string key, object? instance) { System.ThrowHelper.ThrowIfNull(configuration, "configuration"); configuration.GetSection(key).Bind(instance); } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze the type of instance so its members may be trimmed")] public static void Bind(this IConfiguration configuration, object? instance) { configuration.Bind(instance, null); } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze the type of instance so its members may be trimmed")] public static void Bind(this IConfiguration configuration, object? instance, Action? configureOptions) { System.ThrowHelper.ThrowIfNull(configuration, "configuration"); if (instance != null) { BinderOptions binderOptions = new BinderOptions(); configureOptions?.Invoke(binderOptions); BindingPoint bindingPoint = new BindingPoint(instance, isReadOnly: true); BindInstance(instance.GetType(), bindingPoint, configuration, binderOptions, isParentCollection: false); } } [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static T? GetValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration, string key) { return configuration.GetValue(key, default(T)); } [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] [return: NotNullIfNotNull("defaultValue")] public static T? GetValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(this IConfiguration configuration, string key, T defaultValue) { return (T)configuration.GetValue(typeof(T), key, defaultValue); } [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] public static object? GetValue(this IConfiguration configuration, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string key) { return configuration.GetValue(type, key, null); } [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] [return: NotNullIfNotNull("defaultValue")] public static object? GetValue(this IConfiguration configuration, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string key, object? defaultValue) { System.ThrowHelper.ThrowIfNull(configuration, "configuration"); System.ThrowHelper.ThrowIfNull(type, "type"); IConfigurationSection section = configuration.GetSection(key); string value = section.Value; if (value != null) { return ConvertValue(type, value, section.Path); } return defaultValue; } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze property.PropertyType so its members may be trimmed.")] private static void BindProperties(object instance, IConfiguration configuration, BinderOptions options, ParameterInfo[] constructorParameters) { List allProperties = GetAllProperties(instance.GetType()); if (options.ErrorOnUnknownConfiguration) { HashSet hashSet = new HashSet(allProperties.Select((PropertyInfo mp) => mp.Name), StringComparer.OrdinalIgnoreCase); List list = null; foreach (IConfigurationSection child in configuration.GetChildren()) { if (!hashSet.Contains(child.Key)) { (list ?? (list = new List())).Add("'" + child.Key + "'"); } } if (list != null) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_MissingConfig, "ErrorOnUnknownConfiguration", "BinderOptions", instance.GetType(), string.Join(", ", list))); } } foreach (PropertyInfo property in allProperties) { if (constructorParameters == null || !constructorParameters.Any((ParameterInfo p) => p.Name == property.Name)) { BindProperty(property, instance, configuration, options); } else { ResetPropertyValue(property, instance, options); } } } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze property.PropertyType so its members may be trimmed.")] private static void ResetPropertyValue(PropertyInfo property, object instance, BinderOptions options) { if ((object)property.GetMethod != null && (object)property.SetMethod != null && (options.BindNonPublicProperties || (property.GetMethod.IsPublic && property.SetMethod.IsPublic)) && property.GetMethod.GetParameters().Length == 0) { property.SetValue(instance, property.GetValue(instance)); } } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze property.PropertyType so its members may be trimmed.")] private static void BindProperty(PropertyInfo property, object instance, IConfiguration config, BinderOptions options) { if (!(property.GetMethod == null) && (options.BindNonPublicProperties || property.GetMethod.IsPublic) && property.GetMethod.GetParameters().Length == 0) { BindingPoint bindingPoint = new BindingPoint(() => property.GetValue(instance), (object)property.SetMethod == null || (!property.SetMethod.IsPublic && !options.BindNonPublicProperties)); BindInstance(property.PropertyType, bindingPoint, config.GetSection(GetPropertyName(property)), options, isParentCollection: false); if (!bindingPoint.IsReadOnly && bindingPoint.Value != null) { property.SetValue(instance, bindingPoint.Value); } } } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] private static void BindInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, BindingPoint bindingPoint, IConfiguration config, BinderOptions options, bool isParentCollection) { if (type == typeof(IConfigurationSection)) { bindingPoint.TrySetValue(config); } else { if (config == null) { return; } IConfigurationSection configurationSection = config as IConfigurationSection; string text = configurationSection?.Value; if (text != null && TryConvertValue(type, text, configurationSection?.Path, out var result, out var error)) { if (error != null) { throw error; } bindingPoint.TrySetValue(result); } else if (config.GetChildren().Any()) { if (type.IsArray || IsImmutableArrayCompatibleInterface(type)) { if (!bindingPoint.IsReadOnly) { bindingPoint.SetValue(BindArray(type, (IEnumerable)bindingPoint.Value, config, options)); } return; } if (TypeIsASetInterface(type)) { if (!bindingPoint.IsReadOnly || bindingPoint.Value != null) { object obj = BindSet(type, (IEnumerable)bindingPoint.Value, config, options); if (!bindingPoint.IsReadOnly && obj != null) { bindingPoint.SetValue(obj); } } return; } if (TypeIsADictionaryInterface(type)) { if (!bindingPoint.IsReadOnly || bindingPoint.Value != null) { object obj2 = BindDictionaryInterface(bindingPoint.Value, type, config, options); if (!bindingPoint.IsReadOnly && obj2 != null) { bindingPoint.SetValue(obj2); } } return; } ParameterInfo[] constructorParameters = null; if (bindingPoint.Value == null) { if (bindingPoint.IsReadOnly) { return; } Type type2 = ((type.IsInterface && type.IsConstructedGenericType) ? type.GetGenericTypeDefinition() : null); if ((object)type2 != null && (type2 == typeof(ICollection<>) || type2 == typeof(IList<>))) { Type type3 = typeof(List<>).MakeGenericType(type.GenericTypeArguments); bindingPoint.SetValue(Activator.CreateInstance(type3)); } else { bindingPoint.SetValue(CreateInstance(type, config, options, out constructorParameters)); } } Type type4 = FindOpenGenericInterface(typeof(IDictionary<, >), type); if (type4 != null) { BindDictionary(bindingPoint.Value, type4, config, options); return; } Type type5 = FindOpenGenericInterface(typeof(ICollection<>), type); if (type5 != null) { BindCollection(bindingPoint.Value, type5, config, options); } else { BindProperties(bindingPoint.Value, config, options, constructorParameters); } } else if (isParentCollection && bindingPoint.Value == null && string.IsNullOrEmpty(text)) { bindingPoint.TrySetValue(CreateInstance(type, config, options, out var _)); } } } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("In case type is a Nullable, cannot statically analyze what the underlying type is so its members may be trimmed.")] private static object CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type, IConfiguration config, BinderOptions options, out ParameterInfo[] constructorParameters) { constructorParameters = null; if (type.IsInterface || type.IsAbstract) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_CannotActivateAbstractOrInterface, type)); } ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public); bool flag = type.IsValueType || constructors.Any((ConstructorInfo ctor) => ctor.GetParameters().Length == 0); if (!type.IsValueType && constructors.Length == 0) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_MissingPublicInstanceConstructor, type)); } if (constructors.Length > 1 && !flag) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_MultipleParameterizedConstructors, type)); } if (constructors.Length == 1 && !flag) { ConstructorInfo constructorInfo = constructors[0]; ParameterInfo[] parameters = constructorInfo.GetParameters(); if (!CanBindToTheseConstructorParameters(parameters, out var nameOfInvalidParameter)) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_CannotBindToConstructorParameter, type, nameOfInvalidParameter)); } List allProperties = GetAllProperties(type); if (!DoAllParametersHaveEquivalentProperties(parameters, allProperties, out var missing)) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_ConstructorParametersDoNotMatchProperties, type, missing)); } object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { array[i] = BindParameter(parameters[i], type, config, options); } constructorParameters = parameters; return constructorInfo.Invoke(array); } object obj; try { obj = Activator.CreateInstance(Nullable.GetUnderlyingType(type) ?? type); } catch (Exception innerException) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_FailedToActivate, type), innerException); } return obj ?? throw new InvalidOperationException(System.SR.Format(System.SR.Error_FailedToActivate, type)); } private static bool DoAllParametersHaveEquivalentProperties(ParameterInfo[] parameters, List properties, out string missing) { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (PropertyInfo property in properties) { hashSet.Add(property.Name); } List list = new List(); for (int i = 0; i < parameters.Length; i++) { string name = parameters[i].Name; if (!hashSet.Contains(name)) { list.Add(name); } } missing = string.Join(",", list); return missing.Length == 0; } private static bool CanBindToTheseConstructorParameters(ParameterInfo[] constructorParameters, out string nameOfInvalidParameter) { nameOfInvalidParameter = string.Empty; foreach (ParameterInfo parameterInfo in constructorParameters) { if (parameterInfo.IsOut || parameterInfo.IsIn || parameterInfo.ParameterType.IsByRef) { nameOfInvalidParameter = parameterInfo.Name; return false; } } return true; } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the value objects in the dictionary so its members may be trimmed.")] private static object BindDictionaryInterface(object source, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type dictionaryType, IConfiguration config, BinderOptions options) { Type type = dictionaryType.GenericTypeArguments[0]; Type type2 = dictionaryType.GenericTypeArguments[1]; bool isEnum = type.IsEnum; bool flag = type == typeof(sbyte) || type == typeof(byte) || type == typeof(short) || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong); if (type != typeof(string) && !isEnum && !flag) { return null; } MethodInfo method = dictionaryType.GetMethod("Add", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if ((object)method == null || source == null) { dictionaryType = typeof(Dictionary<, >).MakeGenericType(type, type2); object obj = Activator.CreateInstance(dictionaryType); method = dictionaryType.GetMethod("Add", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (source is IEnumerable enumerable) { Type type3 = typeof(KeyValuePair<, >).MakeGenericType(type, type2); PropertyInfo property = type3.GetProperty("Key", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo property2 = type3.GetProperty("Value", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object[] array = new object[2]; foreach (object item in enumerable) { object obj2 = property.GetMethod.Invoke(item, null); object obj3 = property2.GetMethod.Invoke(item, null); array[0] = obj2; array[1] = obj3; method.Invoke(obj, array); } } source = obj; } BindDictionary(source, dictionaryType, config, options); return source; } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the value objects in the dictionary so its members may be trimmed.")] private static void BindDictionary(object dictionary, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type dictionaryType, IConfiguration config, BinderOptions options) { Type type = dictionaryType.GenericTypeArguments[0]; Type type2 = dictionaryType.GenericTypeArguments[1]; bool isEnum = type.IsEnum; bool flag = type == typeof(sbyte) || type == typeof(byte) || type == typeof(short) || type == typeof(ushort) || type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong); if (type != typeof(string) && !isEnum && !flag) { return; } MethodInfo tryGetValue = dictionaryType.GetMethod("TryGetValue", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo property = dictionaryType.GetProperty("Item", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (IConfigurationSection child in config.GetChildren()) { try { object key = (isEnum ? Enum.Parse(type, child.Key, ignoreCase: true) : (flag ? Convert.ChangeType(child.Key, type) : child.Key)); BindingPoint bindingPoint = new BindingPoint(delegate { object[] array = new object[2] { key, null }; return (!(bool)tryGetValue.Invoke(dictionary, array)) ? null : array[1]; }, isReadOnly: false); BindInstance(type2, bindingPoint, child, options, isParentCollection: true); if (bindingPoint.HasNewValue) { property.SetValue(dictionary, bindingPoint.Value, new object[1] { key }); } } catch (Exception innerException) { if (options.ErrorOnUnknownConfiguration) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_GeneralErrorWhenBinding, "ErrorOnUnknownConfiguration"), innerException); } } } } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the object collection so its members may be trimmed.")] private static void BindCollection(object collection, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type collectionType, IConfiguration config, BinderOptions options) { Type type = collectionType.GenericTypeArguments[0]; MethodInfo method = collectionType.GetMethod("Add", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (IConfigurationSection child in config.GetChildren()) { try { BindingPoint bindingPoint = new BindingPoint(); BindInstance(type, bindingPoint, child, options, isParentCollection: true); if (bindingPoint.HasNewValue) { method?.Invoke(collection, new object[1] { bindingPoint.Value }); } } catch (Exception innerException) { if (options.ErrorOnUnknownConfiguration) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_GeneralErrorWhenBinding, "ErrorOnUnknownConfiguration"), innerException); } } } } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the Array so its members may be trimmed.")] private static Array BindArray(Type type, IEnumerable source, IConfiguration config, BinderOptions options) { Type type2; if (type.IsArray) { if (type.GetArrayRank() > 1) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_UnsupportedMultidimensionalArray, type)); } type2 = type.GetElementType(); } else { type2 = type.GetGenericArguments()[0]; } List list = new List(); if (source != null) { foreach (object item in source) { list.Add(item); } } foreach (IConfigurationSection child in config.GetChildren()) { BindingPoint bindingPoint = new BindingPoint(); try { BindInstance(type2, bindingPoint, child, options, isParentCollection: true); if (bindingPoint.HasNewValue) { list.Add(bindingPoint.Value); } } catch (Exception innerException) { if (options.ErrorOnUnknownConfiguration) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_GeneralErrorWhenBinding, "ErrorOnUnknownConfiguration"), innerException); } } } Array array = Array.CreateInstance(type2, list.Count); ((ICollection)list).CopyTo(array, 0); return array; } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze what the element type is of the Array so its members may be trimmed.")] private static object BindSet(Type type, IEnumerable source, IConfiguration config, BinderOptions options) { Type type2 = type.GetGenericArguments()[0]; bool isEnum = type2.IsEnum; if (type2 != typeof(string) && !isEnum) { return null; } object[] array = new object[1]; MethodInfo method = type.GetMethod("Add", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if ((object)method == null || source == null) { Type type3 = typeof(HashSet<>).MakeGenericType(type2); object obj = Activator.CreateInstance(type3); method = type3.GetMethod("Add", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (source != null) { foreach (object item in source) { array[0] = item; method.Invoke(obj, array); } } source = (IEnumerable)obj; } foreach (IConfigurationSection child in config.GetChildren()) { BindingPoint bindingPoint = new BindingPoint(); try { BindInstance(type2, bindingPoint, child, options, isParentCollection: true); if (bindingPoint.HasNewValue) { array[0] = bindingPoint.Value; method.Invoke(source, array); } } catch (Exception innerException) { if (options.ErrorOnUnknownConfiguration) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_GeneralErrorWhenBinding, "ErrorOnUnknownConfiguration"), innerException); } } } return source; } [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] private static bool TryConvertValue([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string value, string path, out object result, out Exception error) { error = null; result = null; if (type == typeof(object)) { result = value; return true; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { if (string.IsNullOrEmpty(value)) { return true; } return TryConvertValue(Nullable.GetUnderlyingType(type), value, path, out result, out error); } TypeConverter converter = TypeDescriptor.GetConverter(type); if (converter.CanConvertFrom(typeof(string))) { try { result = converter.ConvertFromInvariantString(value); } catch (Exception innerException) { error = new InvalidOperationException(System.SR.Format(System.SR.Error_FailedBinding, path, type), innerException); } return true; } if (type == typeof(byte[])) { try { result = Convert.FromBase64String(value); } catch (FormatException innerException2) { error = new InvalidOperationException(System.SR.Format(System.SR.Error_FailedBinding, path, type), innerException2); } return true; } return false; } [RequiresUnreferencedCode("In case the type is non-primitive, the trimmer cannot statically analyze the object's type so its members may be trimmed.")] private static object ConvertValue([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, string value, string path) { TryConvertValue(type, value, path, out var result, out var error); if (error != null) { throw error; } return result; } private static bool TypeIsADictionaryInterface(Type type) { if (!type.IsInterface || !type.IsConstructedGenericType) { return false; } Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (!(genericTypeDefinition == typeof(IDictionary<, >))) { return genericTypeDefinition == typeof(IReadOnlyDictionary<, >); } return true; } private static bool IsImmutableArrayCompatibleInterface(Type type) { if (!type.IsInterface || !type.IsConstructedGenericType) { return false; } Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (!(genericTypeDefinition == typeof(IEnumerable<>)) && !(genericTypeDefinition == typeof(IReadOnlyCollection<>))) { return genericTypeDefinition == typeof(IReadOnlyList<>); } return true; } private static bool TypeIsASetInterface(Type type) { if (!type.IsInterface || !type.IsConstructedGenericType) { return false; } return type.GetGenericTypeDefinition() == typeof(ISet<>); } private static Type FindOpenGenericInterface(Type expected, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type actual) { if (actual.IsGenericType && actual.GetGenericTypeDefinition() == expected) { return actual; } Type[] interfaces = actual.GetInterfaces(); foreach (Type type in interfaces) { if (type.IsGenericType && type.GetGenericTypeDefinition() == expected) { return type; } } return null; } private static List GetAllProperties([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { List list = new List(); Type type2 = type; while (type2 != typeof(object)) { PropertyInfo[] properties = type2.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); if ((object)setMethod == null || !setMethod.IsVirtual || setMethod == setMethod.GetBaseDefinition()) { list.Add(propertyInfo); } } type2 = type2.BaseType; } return list; } [RequiresDynamicCode("Binding strongly typed objects to configuration values requires generating dynamic code at runtime, for example instantiating generic types.")] [RequiresUnreferencedCode("Cannot statically analyze property.PropertyType so its members may be trimmed.")] private static object BindParameter(ParameterInfo parameter, Type type, IConfiguration config, BinderOptions options) { string name = parameter.Name; if (name == null) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_ParameterBeingBoundToIsUnnamed, type)); } BindingPoint bindingPoint = new BindingPoint(config.GetSection(name).Value); BindInstance(parameter.ParameterType, bindingPoint, config.GetSection(name), options, isParentCollection: false); if (bindingPoint.Value == null) { if (!ParameterDefaultValue.TryGetDefaultValue(parameter, out object defaultValue)) { throw new InvalidOperationException(System.SR.Format(System.SR.Error_ParameterHasNoMatchingConfig, type, name)); } bindingPoint.SetValue(defaultValue); } return bindingPoint.Value; } private static string GetPropertyName(PropertyInfo property) { System.ThrowHelper.ThrowIfNull(property, "property"); foreach (CustomAttributeData customAttributesDatum in property.GetCustomAttributesData()) { if (!(customAttributesDatum.AttributeType != typeof(ConfigurationKeyNameAttribute))) { if (customAttributesDatum.ConstructorArguments.Count != 1) { break; } string text = customAttributesDatum.ConstructorArguments[0].Value?.ToString(); return (!string.IsNullOrWhiteSpace(text)) ? text : property.Name; } } return property.Name; } } }