示例#1
0
        /// <summary>
        /// Loads/serializes an xml file into a settings class based on class type
        /// </summary>
        /// <param name="xmlfile">The path to the file</param>
        /// <param name="SettingsClass">The type of the settings class to load into</param>
        /// <param name="propertiesToExclude">A string list of properties (in the class) to not look for</param>
        /// <param name="classInstance">The actual object to append the xml settings to</param>
        /// <returns></returns>
        public static bool LoadSettings(string xmlfile, Type SettingsClass, string[] propertiesToExclude, object classInstance)
        {
            //first check if the file even exists
            if (!File.Exists(xmlfile))
            {
                Logging.Warning("Xml settings file {0} does not exist, using defaults set in class{1}{2}", xmlfile, SettingsClass.GetType().ToString(), Environment.NewLine);
                return(false);
            }
            //get all fields from the class
            FieldInfo[] fields = SettingsClass.GetFields();
            //get all types from the types in the class
            List <Type> typesOfTypesInClass = new List <Type>();

            foreach (FieldInfo fieldInClass in fields)
            {
                //https://stackoverflow.com/questions/5090224/reflection-get-type-of-fieldinfo-object
                Type t = fieldInClass.FieldType;
                if (!typesOfTypesInClass.Contains(t))
                {
                    typesOfTypesInClass.Add(t);
                }
            }
            //now we have a list of all "types" that exist in the class
            //parse the xml list
            XmlDocument doc = new XmlDocument();

            try
            {
                doc.Load(xmlfile);
            }
            catch (XmlException ex)
            {
                Logging.Error("Failed to load {0}, using defaults set in class{1}{2}{3}", xmlfile, SettingsClass.GetType().ToString(), Environment.NewLine, ex.ToString());
                return(false);
            }
            //using child of child rather than xpath gets around the fact that the root element name has changed or can change
            XmlNodeList settings = doc.ChildNodes[0].ChildNodes;

            //legacy compatibility: if it's modpackSettings, there's some V1 bad names that need to be manually parsed
            if (SettingsClass.Equals(typeof(ModpackSettings)))
            {
                ModpackSettings.ApplyOldSettings(settings);
            }
            for (int i = 0; i < settings.Count; i++)
            {
                //verify that the setting name in xml matches a fieldInfo property in the class
                FieldInfo[] matches = fields.Where(f => f.Name.Equals(settings[i].Name)).ToArray();
                //Logging.WriteToLog(string.Empty + matches.Count() + " matches for xml setting name " + settings[i].Name, Logfiles.Application, LogLevel.Debug);
                if (matches.Count() > 1)
                {
                    throw new BadMemeException("ugh");
                }
                else if (matches.Count() == 0)
                {
                    Logging.Warning("no match for xml setting {0}", settings[i].Name);
                }
                else
                {
                    FieldInfo settingField = matches[0];
                    //we have, based on name, matched the xml property to a property in the class
                    //now set the value
                    //BUT also check to make sure the item is not on the blacklist
                    if (propertiesToExclude != null && propertiesToExclude.Contains(settingField.Name))
                    {
                        Logging.Debug("Property {0} matched to exclusion list, skipping", settingField.Name);
                        continue;
                    }
                    //get the type of the field and make sure it actually exists in the list (it should)
                    if (typesOfTypesInClass.Contains(settingField.FieldType))
                    {
                        //since the type exists, it *should* save
                        //https://stackoverflow.com/questions/2380467/c-dynamic-parse-from-system-type
                        try
                        {
                            var converter = TypeDescriptor.GetConverter(settingField.FieldType);
                            if (classInstance != null)
                            {
                                settingField.SetValue(classInstance, converter.ConvertFrom(settings[i].InnerText));
                            }
                            else
                            {
                                settingField.SetValue(SettingsClass, converter.ConvertFrom(settings[i].InnerText));
                            }
                        }
                        catch (Exception e)
                        {
                            Logging.Debug("failed to load property to memory {0}{1}{2}", settingField.Name, Environment.NewLine, e.ToString());
                        }
                    }
                    else
                    {
                        throw new BadMemeException("hmmmmmm");
                    }
                }
            }
            return(true);
        }