internal override bool DoWork(SettingTypeModel model) { if (!IsCollection(model.Member)) { return(base.DoWork(model)); } var args = model.Member.PropertyType.GetGenericArguments(); if (args.Length > 1) { Trace.TraceWarning($"Mash.AppSettings: Unsupported property type with {args.Length} generic parameters."); } Type itemType = args.First(); // Check to see if an instance already exists dynamic property = model.Member.GetGetMethod().Invoke(model.SettingsClass, null); if (property == null) { // No instance exists so create a List<T> Type listType = typeof(List <>) .GetGenericTypeDefinition() .MakeGenericType(itemType); dynamic instance = Activator.CreateInstance(listType); // Assign the instance to the class property model.Member.SetValue(model.SettingsClass, instance); property = instance; } var loadedValue = LoadValue(model); if (loadedValue == null) { return(false); } foreach (var item in loadedValue.Split(_separators, StringSplitOptions.RemoveEmptyEntries)) { // There's a dynamic binding issue with non-public types. One fix is to cast to IList to ensure the call to Add succeeds // but that requires basing this feature off of IList<T> and not ICollection<T>. // This does not work for ICollection because it does not include the Add method (only ICollection<T> does) // http://stackoverflow.com/questions/15920844/system-collections-generic-ilistobject-does-not-contain-a-definition-for-ad property.Add(TypeParser.GetTypedValue(itemType, item.Trim())); } return(true); }
internal override bool DoWork(SettingTypeModel model) { // Check if the property is meant to load a specific connection string if (!IsConnectionStringSettingType(model.Member)) { return(base.DoWork(model)); } Trace.TraceInformation($"Mash.AppSettings: Loading connection string into [{model.Member.Name}]."); string loadedConnectionString = null; if (model.DevLoader != null) { loadedConnectionString = model.DevLoader.GetConnectionString(model.SettingName); Trace.TraceInformation($"Mash.AppSettings: attempting override connection string {model.SettingName} from dev settings with [{loadedConnectionString}]"); } if (String.IsNullOrWhiteSpace(loadedConnectionString)) { loadedConnectionString = model.SettingLoader.GetConnectionString(model.SettingName); } if (!CheckIfSettingIsValid(loadedConnectionString, model.SettingName)) { if (IsSettingRequired(model.Member)) { throw new ArgumentException("Mash.AppSettings: The connection string could not be found.", model.SettingName); } return(true); } var parsedConnectionString = TypeParser.GetTypedValue(model.Member.PropertyType, loadedConnectionString); model.Member.SetValue(model.SettingsClass, parsedConnectionString); return(true); }
/// <summary> /// Loads settings for the public properties in the specified class using the specified settings loader /// </summary> /// <typeparam name="T">The type of settings class being loaded</typeparam> /// <param name="settingLoader">The specified setting loader to use</param> /// <param name="settingsClass">The settings class to save settings into</param> /// <returns>True if successful</returns> /// <exception cref="ArgumentNullException">The parameters must be valid</exception> /// <exception cref=AggregateException">Any mismatch in setting name or type loading will be reported</exception> /// <remarks>Check trace statements for any additional issues encountered during loading</remarks> public static bool Load <T>(ISettingLoader settingLoader, ref T settingsClass) where T : class { if (settingLoader == null) { throw new ArgumentNullException(nameof(settingLoader)); } if (settingsClass == null) { throw new ArgumentNullException(nameof(settingsClass)); } var members = typeof(T).FindMembers( MemberTypes.Property, BindingFlags.Instance | BindingFlags.Public, HasAttribute, null); var exceptions = new List <Exception>(); foreach (PropertyInfo member in members) { string settingName = member.Name; var attr = member.GetCustomAttribute <AppSettingAttribute>(); if (attr != null && attr.Key != null) { settingName = attr.Key; } Trace.TraceInformation($"Loading class member [{member.Name}] as [{settingName}]."); if (!member.CanWrite) { Trace.TraceWarning($"Property [{settingsClass.GetType()}.{member.Name}] is not writeable; skipping."); continue; } try { // Check if the property is meant to load all of the connection strings if (IsSupportedConnectionStringsType(member)) { Trace.TraceInformation($"Loading all connection strings into [{member.Name}]."); member.SetValue(settingsClass, settingLoader.GetConnectionStrings()); continue; } // Check if the property is meant to load a specific connection string if (IsConnectionStringSettingType(member)) { Trace.TraceInformation($"Loading connection string into [{member.Name}]."); var loadedConnectionString = settingLoader.GetConnectionString(settingName); if (!CheckIfSettingIsValid(loadedConnectionString, settingName)) { if (IsSettingRequired(member)) { exceptions.Add(new ArgumentException("The connection string could not be found.", settingName)); } continue; } var parsedConnectionString = TypeParser.GetTypedValue(member.PropertyType, loadedConnectionString); member.SetValue(settingsClass, parsedConnectionString); continue; } // Load normal setting types var loadedSetting = settingLoader.GetSetting(settingName); if (!CheckIfSettingIsValid(loadedSetting, settingName)) { if (IsSettingRequired(member)) { exceptions.Add(new ArgumentException("The setting could not be found.", settingName)); } continue; } var parsedSetting = TypeParser.GetTypedValue(member.PropertyType, loadedSetting); member.SetValue(settingsClass, parsedSetting); } catch (Exception ex) { Trace.TraceError($"Loading of setting [{settingName}] failed with:\r\n{ex}."); exceptions.Add(ex); } } if (exceptions.Any()) { throw new AggregateException( $"{exceptions.Count} errors loading settings.", exceptions); } return(true); }