je courais dans toutes sortes de bugs qui font un Xml Singleton classe et a fini par mise à la ferraille que je avait des poignées partout. Je l'ai remplacé en utilisant deux façons. Une version en lecture seule qui était pour la lecture des données, et une seconde méthode Using/instruction pour l'écriture des modifications.
Ce en général est le modèle que j'utilise:
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;
}
}
Je n'ai pas utilisé le sérialiseur, donc je ne sais pas si mon modèle s'adaptera pour vous. Je préfère XElement. Donc, pour l'utiliser, vous devrez probablement écrire une classe singleton qui utilise votre classe XmlSerialize non-singleton. Vous n'y auriez accès qu'à travers le singleton.
Mais voici comment je finirais l'utiliser comme est:
string settingA = Settings.Read.SettingA;
Pour enregistrer une valeur, il serait:
Settings.Write(s => s.SettingA = "new value");
DI gestion de vie des conteneurs est généralement un meilleur choix que le Motif Singleton. Voir http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons – TrueWill