Edit Object with xml without creating new Instance

后端 未结 2 796
盖世英雄少女心
盖世英雄少女心 2021-01-15 23:47

I have a class which needs to be a Singleton. It must also be able to load and save its field data in an xml file.

The following method will return a new instance,

相关标签:
2条回答
  • 2021-01-16 00:02

    I used to run into all sorts of bugs making an Xml Singleton class and ended up scrapping it as I had handles all over the place. I replaced it with using two ways. One a read-only version that was for reading data, and a second Using method/statement for writing changes.

    This in general is the pattern I use:

    public class Settings : IDisposable
    {
        string file = "my settings file";
        XElement root;
    
        private Settings()
        { 
            root = XElement.Load(file);           
        }
    
        private void Dispose()
        {
            root.Save(file);
        }
    
        public static Settings Read { get { return new Settings(); } } // return read-only version
    
        public static void Write(Action<Settings> handler)
        {
            using(Setting settings = new Settings())
                handler(settings);
        }
    
        // below here is implentation specific
    
        public XElement Root { get { return root; } }
    
        public string SettingA 
        { 
            get { return (string)(Root.Attribute("SettingA") ?? (object)string.Empty); }
            set { Set(Root, "SettingsA", value, true); }
        }
    
        // I wrote this for another StackOverflow thread
        /// <summary>
        /// Set any value via its .ToString() method.
        /// <para>Returns XElement of source or the new XElement if is an ELEMENT</para>
        /// </summary>
        /// <param name="isAttribute">true for ATTRIBUTE or false for ELEMENT</param>
        /// <returns>source or XElement value</returns>
        private XElement Set(XElement source, string name, object value, bool isAttribute)
        {
            string sValue = value.ToString();
            XElement eValue = source.Element(name), result = source;
            XAttribute aValue = source.Attribute(name);
            if (null != eValue)
                eValue.ReplaceWith(result = new XElement(name, sValue));
            else if (null != aValue)
                aValue.ReplaceWith(new XAttribute(name, sValue));
            else if (isAttribute)
                source.Add(new XAttribute(name, sValue));
            else
                source.Add(result = new XElement(name, sValue));
            return result;
        }
    
        /// <summary>
        /// Replace with for XAttribute
        /// </summary>
        /// <param name="source"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static XAttribute ReplaceWith(this XAttribute source, XAttribute value)
        {
            XElement parent = source.Parent;
            if (null == parent)
                throw new Exception("Source has no parent");
            source.Remove();
            parent.Add(value);
            return value;
        }
    
    }
    

    I've not used the serializer, so don't know if my pattern will fit for you. I prefer XElement.

    So to use this you'd probably write a singleton class that makes use of your non-singleton XmlSerialize class. You'd only access it through the singleton.

    But this is how I'd end up using it as is:

    string settingA = Settings.Read.SettingA;
    

    To save a value it would be:

    Settings.Write(s => s.SettingA = "new value");
    
    0 讨论(0)
  • 2021-01-16 00:03

    why dont you have something like

    public Class TheClassHoldingYourObject
    {
        private static XmlSerializer _instance;
        public static Settings Load() 
        { 
            if(_instance != null) return _instance
            using (Stream stream = File.OpenRead(FileName)) 
            { 
                  XmlSerializer serializer = new XmlSerializer(typeof(Settings)); 
                  return (Settings)serializer.Deserialize(stream); 
            } 
        }
     }
    

    Now you will always get the same instance

    0 讨论(0)
提交回复
热议问题