13

「static readonly T Instance = new T();」を使用するシングルトンがあります。パターン。しかし、T が使い捨てであり、実際には単体テストのために破棄する必要がある場合に遭遇しました。このパターンを変更して使い捨てシングルトンをサポートするにはどうすればよいですか?

私が望むインターフェースは次のようなものです:

var x = Foo.Instance;
var y = Foo.Instance; // x == y
...
x.Release(); // this causes the next Foo.Instance to return a fresh object
             // also, it assumes no further operations on x/y will be performed.

注 - もちろん、パターンはスレッドセーフでなければなりません。

編集- 本番コードの目的で、これは真のシングルトンです。問題は、いくつかのファイルをロックすることです。そのため、単体テストでのクリーンアップのために、それを破棄する必要があります。

可能であれば、再利用できるパターンも希望します。

4

8 に答える 8

15

正直なところ、その時点で、それをもはやシングルトンとは考えていないと思います。

特に、クライアントがシングルトンを使用している場合、それを処分する必要があるとは本当に思っていません。

本番コードは何をする予定ですか?

編集:ユニットテストとユニットテストのみにこれが本当に必要な場合(率直に言って、設計の観点から疑わしいように聞こえます)、リフレクションを使用してフィールドをいつでもいじることができます。それが本当にシングルトンであるべきなのか、それとも本当に使い捨てであるべきなのかを判断する方が良いでしょう.2一緒になることはめったにありません.

于 2008-10-22T13:21:44.210 に答える
13

としてマークReleaseinternal、属性を使用して、InternalsVisibleTo単体テスト アセンブリにのみ公開します。それを行うか、自分のアセンブリの誰かがそれを呼び出すことを警戒している場合は、それをマークしてprivate、リフレクションを使用してアクセスできます。

Disposeシングルトン インスタンスでメソッドを呼び出すファイナライザーをシングルトンで使用します。

プロダクション コードでは、 のアンロードのみがAppDomainシングルトンの破棄を引き起こします。テスト コードでは、Release自分自身への呼び出しを開始できます。

于 2008-10-22T14:00:17.953 に答える
4

シングルトンは使い捨てにすべきではありません。限目。誰かが時期尚早に Dispose を呼び出すと、アプリケーションは再起動するまで機能しなくなります。

于 2008-10-22T13:42:31.017 に答える
2
 public class Foo : IDisposable
  { [ThreadStatic] static Foo _instance = null;

    private Foo() {IsReleased = false;}

    public static Foo Instance
     { get
        { if (_instance == null) _instance = new Foo();
          return _instance;
        }
     }

    public void Release()
     { IsReleased = true;
       Foo._instance = null;
     }

    void IDisposable.Dispose() { Release(); }

    public bool IsReleased { get; private set;}

  }
于 2008-10-22T13:38:48.963 に答える
0

ネストされたレイジーシングルトン(ここを参照)をいくつかの簡単な変更で使用できます。

public sealed class Singleton : IDisposable
{
    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (!Nested.released)
                return Nested.instance;
            else
                throw new ObjectDisposedException();
        }
    }

    public void Dispose()
    {
         disposed = true;
         // Do release stuff here
    }

    private bool disposed = false;

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

オブジェクトが破棄されている場合は、オブジェクトのすべてのパブリックメソッド/プロパティでObjectDisposedExceptionをスローすることを忘れないでください。

また、Disposeが呼び出されない場合に備えて、オブジェクトのファイナライザーメソッドを提供する必要があります。IDisposableを正しく実装する方法についてはこちらをご覧ください。

于 2008-10-22T13:36:04.493 に答える
0

クラスがIDisposableを実装している場合(あなたが示唆しているように)、x.Dispose()を呼び出すだけです。

于 2008-10-22T13:38:29.293 に答える
0

単体テストでは、「手動」インスタンスを使用できます(ただし、オブジェクトをインスタンス化する方法が必要になります)。

あなたの場合、おそらくファクトリパターン(抽象/メソッド-あなたのケースに最適な方)をシングルトンと組み合わせて使用​​する方がよいでしょう。

シングルトンが使用済みオブジェクトを適切に処理したかどうかをテストする場合(単体テストで)、ファクトリメソッドを使用します。それ以外の場合は、シングルトンパターンを使用します。

ちなみに、シングルトンソースコードにアクセスできない場合、または変更が許可されていない場合は、別のシングルトンにラップして、新しいシングルトンのすべてのロジックを提供することをお勧めします(プロキシのように)。やり過ぎのように聞こえますが、実行可能な解決策になる可能性があります。

また、アクセスを制御できるようにするために、ファクトリを提供し、オブジェクトが破棄されていない場合にのみクライアントが新しいオブジェクトを取得できるようにします。

于 2008-10-22T13:39:53.830 に答える
0

使い捨てのシングルトンを作成する別のオプションは、SandCastle の[Singleton]属性をクラスに使用することです。その後、Castle フレームワークがすべての使い捨てのシングルトン オブジェクトを破棄します。

于 2009-04-15T04:04:46.553 に答える