// transforms binding data to appropriate resolver (appsetting, autoresolve, or originalValue)
        private BindingDataResolver GetResolver(PropertyInfo propInfo, INameResolver nameResolver, BindingDataContract contract)
        {
            object originalValue = propInfo.GetValue(_source);
            AppSettingAttribute  appSettingAttr  = propInfo.GetCustomAttribute <AppSettingAttribute>();
            AutoResolveAttribute autoResolveAttr = propInfo.GetCustomAttribute <AutoResolveAttribute>();

            if (appSettingAttr != null && autoResolveAttr != null)
            {
                throw new InvalidOperationException($"Property '{propInfo.Name}' cannot be annotated with both AppSetting and AutoResolve.");
            }

            // first try to resolve with app setting
            if (appSettingAttr != null)
            {
                return(GetAppSettingResolver((string)originalValue, appSettingAttr, nameResolver, propInfo));
            }
            // try to resolve with auto resolve ({...}, %...%)
            if (autoResolveAttr != null && originalValue != null)
            {
                _autoResolves[propInfo] = autoResolveAttr;
                return(GetTemplateResolver((string)originalValue, autoResolveAttr, nameResolver, propInfo, contract));
            }
            // resolve the original value
            return((newAttr, bindingData) => originalValue);
        }
        public void ItWillSetNameCorrectly(string sectionName)
        {
            var attribute = new AppSettingAttribute(sectionName);

            attribute
            .Name
            .Should()
            .Be(sectionName);
        }
Esempio n. 3
0
        // transforms binding data to appropriate resolver (appsetting, autoresolve, or originalValue)
        private BindingDataResolver GetResolver(PropertyInfo propInfo, INameResolver nameResolver, BindingDataContract contract)
        {
            // Do the attribute lookups once upfront, and then cache them (via func closures) for subsequent runtime usage.
            object originalValue = propInfo.GetValue(_source);
            ConnectionStringAttribute connStrAttr     = propInfo.GetCustomAttribute <ConnectionStringAttribute>();
            AppSettingAttribute       appSettingAttr  = propInfo.GetCustomAttribute <AppSettingAttribute>();
            AutoResolveAttribute      autoResolveAttr = propInfo.GetCustomAttribute <AutoResolveAttribute>();
            Validator validator = GetValidatorFunc(propInfo, appSettingAttr != null);

            if (appSettingAttr == null && autoResolveAttr == null && connStrAttr == null)
            {
                validator(originalValue);

                // No special attributes, treat as literal.
                return((newAttr, bindingData) => originalValue);
            }

            int attrCount = new Attribute[] { connStrAttr, appSettingAttr, autoResolveAttr }.Count(a => a != null);

            if (attrCount > 1)
            {
                throw new InvalidOperationException($"Property '{propInfo.Name}' can only be annotated with one of the types {nameof(AppSettingAttribute)}, {nameof(AutoResolveAttribute)}, and {nameof(ConnectionStringAttribute)}.");
            }

            // attributes only work on string properties.
            if (propInfo.PropertyType != typeof(string))
            {
                throw new InvalidOperationException($"{nameof(ConnectionStringAttribute)}, {nameof(AutoResolveAttribute)}, or {nameof(AppSettingAttribute)} property '{propInfo.Name}' must be of type string.");
            }

            var str = (string)originalValue;

            // first try to resolve with connection string
            if (connStrAttr != null)
            {
                return(GetConfigurationResolver(str, connStrAttr.Default, propInfo, validator, s => _configuration.GetConnectionStringOrSetting(nameResolver.ResolveWholeString(s))));
            }

            // then app setting
            if (appSettingAttr != null)
            {
                return(GetConfigurationResolver(str, appSettingAttr.Default, propInfo, validator, s => _configuration[s]));
            }

            // Must have an [AutoResolve]
            // try to resolve with auto resolve ({...}, %...%)
            return(GetAutoResolveResolver(str, autoResolveAttr, nameResolver, propInfo, contract, validator));
        }
        // transforms binding data to appropriate resolver (appsetting, autoresolve, or originalValue)
        private BindingDataResolver GetResolver(PropertyInfo propInfo, INameResolver nameResolver, BindingDataContract contract)
        {
            // Do the attribute lookups once upfront, and then cache them (via func closures) for subsequent runtime usage.
            object originalValue = propInfo.GetValue(_source);
            AppSettingAttribute  appSettingAttr  = propInfo.GetCustomAttribute <AppSettingAttribute>();
            AutoResolveAttribute autoResolveAttr = propInfo.GetCustomAttribute <AutoResolveAttribute>();
            Validator            validator       = GetValidatorFunc(propInfo, appSettingAttr != null);

            if (appSettingAttr == null && autoResolveAttr == null)
            {
                validator(originalValue);

                // No special attributes, treat as literal.
                return((newAttr, bindingData) => originalValue);
            }

            if (appSettingAttr != null && autoResolveAttr != null)
            {
                throw new InvalidOperationException($"Property '{propInfo.Name}' cannot be annotated with both AppSetting and AutoResolve.");
            }

            // attributes only work on string properties.
            if (propInfo.PropertyType != typeof(string))
            {
                throw new InvalidOperationException($"AutoResolve or AppSetting property '{propInfo.Name}' must be of type string.");
            }
            var str = (string)originalValue;

            // first try to resolve with app setting
            if (appSettingAttr != null)
            {
                return(GetAppSettingResolver(str, appSettingAttr, nameResolver, propInfo, validator));
            }

            // Must have an [AutoResolve]
            // try to resolve with auto resolve ({...}, %...%)
            return(GetAutoResolveResolver(str, autoResolveAttr, nameResolver, propInfo, contract, validator));
        }
        // AppSetting
        internal static BindingDataResolver GetAppSettingResolver(string originalValue, AppSettingAttribute attr, INameResolver nameResolver, PropertyInfo propInfo)
        {
            string appSettingName = originalValue ?? attr.Default;
            string resolvedValue  = string.IsNullOrEmpty(appSettingName) ?
                                    originalValue : nameResolver.Resolve(appSettingName);

            // If a value is non-null and cannot be found, we throw to match the behavior
            // when %% values are not found in ResolveWholeString below.
            if (resolvedValue == null && originalValue != null)
            {
                // It's important that we only log the attribute property name, not the actual value to ensure
                // that in cases where users accidentally use a secret key *value* rather than indirect setting name
                // that value doesn't get written to logs.
                throw new InvalidOperationException($"Unable to resolve value for property '{propInfo.DeclaringType.Name}.{propInfo.Name}'.");
            }
            return((newAttr, bindingData) => resolvedValue);
        }