Exemple #1
0
        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);
        }
Exemple #3
0
        /// <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);
        }