// 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); }
// 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); }