2012-01-17 21 views
1

私はシングルトンである必要があるクラスを持っています。 また、フィールドデータをXMLファイルにロードして保存できる必要があります。新しいインスタンスを作成せずにxmlでオブジェクトを編集

次のメソッドは、私のコードに潜在的なバグを残して、私のシングルトンパターンを壊す新しいインスタンスを返します。私が代わりに全く新しいインスタンスを返すので、私の既存のインスタンス内のデータを更新するために使用することができますどのような方法

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

私はLinqからXmlまでを少し研究しましたが、これの良い例は見つかりませんでした。 フィールドデータをすべて辞書に保存する必要がありますか?

+0

DIコンテナの寿命管理がより通常より良い選択でありますシングルトンパターン。 http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletonsを参照してください – TrueWill

答えて

1

を取得する私は、XMLシングルトンクラスを作成するバグのすべての種類に実行するために使用し、私としてそれを廃棄終わった

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

のようなものを持っていけません場所のいたるところにハンドルがありました。私はそれを2つの方法で置き換えました。 1つはデータを読み取るための読み取り専用バージョンで、もう1つは変更を書き込むためのメソッド/ステートメントの使用です。

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

は、なぜあなたは今、あなたは常に同じインスタンスに

+0

興味のある実際のオブジェクトへの私的参照を保持するシングルトンとしてContainerクラスを持つことは扱いにくい制限的。 「設定」を再読み込みする場合はどうすればよいですか?その場合、XMLからリロードするときに、コード内に「設定」という2つのインスタンスが存在する可能性があります。 –

関連する問題