使用xml编辑对象,而不创建新实例
本文关键字:新实例 实例 创建 编辑 xml 对象 使用 | 更新日期: 2023-09-27 18:20:44
我有一个类需要是Singleton。它还必须能够加载字段数据并将其保存在xml文件中。
下面的方法将返回一个新实例,这打破了我的Singleton模式,在我的代码中留下了潜在的错误。
public Settings Load()
{
using (Stream stream = File.OpenRead(FileName))
{
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
return (Settings)serializer.Deserialize(stream);
}
}
我可以使用什么方法来更新现有实例中的数据,而不是返回一个全新的实例?
我已经研究了一些Linq-to-Xml,但还没有找到任何好的例子。我有必要将所有字段数据保存在字典中吗?
我曾经在创建Xml Singleton类时遇到过各种各样的错误,最后我把它报废了,因为我到处都有句柄。我用两种方式代替了它。一个是只读版本,用于读取数据,另一个是Using方法/语句,用于写入更改。
这通常是我使用的模式:
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类的单例类。您只能通过singleton访问它。
但这就是我最终使用它的方式:
string settingA = Settings.Read.SettingA;
要保存一个值,它将是:
Settings.Write(s => s.SettingA = "new value");
为什么没有这样的东西
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);
}
}
}
现在,您将始终获得相同的实例