Редактировать объект с помощью XML без создания нового экземпляра - PullRequest
1 голос
/ 17 января 2012

У меня есть класс, который должен быть Singleton.Он также должен иметь возможность загружать и сохранять данные своего поля в XML-файле.

Следующий метод возвращает новый экземпляр, который нарушает мой шаблон Singleton, оставляя потенциальные ошибки в моем коде.

public Settings Load()
{
  using (Stream stream = File.OpenRead(FileName))
  {
    XmlSerializer serializer = new XmlSerializer(typeof(Settings));
    return (Settings)serializer.Deserialize(stream);
  }
}

Какой метод я могу использовать для обновления данных в моем существующем экземпляре, вместо того, чтобы возвращать полностью новый экземпляр?

Я немного изучил Linq для Xml, но не нашеллюбой хороший пример этого.Обязательно ли хранить все мои полевые данные в словаре?

Ответы [ 2 ]

1 голос
/ 17 января 2012

Раньше я сталкивался со всевозможными ошибками, создавая класс Xml Singleton, и в итоге отказался от него, так как у меня были повсюду ручки.Я заменил его двумя способами.Одна версия только для чтения, предназначенная для чтения данных, и вторая Использование метода / оператора для записи изменений.

Обычно это шаблон, который я использую:

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

}

Я не использовал сериализатор, поэтому не знаю, подойдет ли мой шаблон для вас.Я предпочитаю XElement.

Поэтому, чтобы использовать это, вы, вероятно, написали бы одноэлементный класс, который использует ваш не одноэлементный класс XmlSerialize.Вы получите доступ к нему только через синглтон.

Но вот как я в итоге смогу использовать его следующим образом:

string settingA = Settings.Read.SettingA;

Чтобы сохранить значение, это будет:

Settings.Write(s => s.SettingA = "new value");
0 голосов
/ 17 января 2012

почему у вас нет что-то вроде

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

Теперь вы всегда получите один и тот же экземпляр

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...