Frage

Ich habe einen Singleton, den die verwendet "statische Nur-Lese-T Instanz = new T ();" Muster. Allerdings lief ich in einem Fall, wo T ist Einweg, und tatsächlich benötigt für Unit-Tests entsorgt werden. Wie kann ich dieses Muster ändern, um eine Einweg Singleton zu unterstützen?

Die Schnittstelle Ich mag würde, ist so etwas wie:

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.

Hinweis - hat das Muster Thread-sicher, natürlich sein

.

Bearbeiten - zum Zweck der Produktion Code, das ist eine wahre Singleton. Die Sache ist, dass es einige Dateien sperrt, und so für die Bereinigung in Unit-Tests haben wir es zu entsorgen.

Ich würde auch ein Muster bevorzugen, die wiederverwendet werden können, wenn möglich.

War es hilfreich?

Lösung

Mark Release als internal und verwenden Sie das InternalsVisibleTo Attribut es zu belichten nur auf das Gerät Testanordnung. Sie können entweder das tun, oder wenn Sie vorsichtig jemand in Ihrer eigenen Montage sind es nennen, können Sie es als private und Zugang markieren es mithilfe von Reflektion.

Verwenden Sie einen Finalizer in Ihrem Singleton, der die Dispose Methode auf der Singleton-Instanz aufruft.

In Produktionscode nur das Entladen einer AppDomain wird die Entsorgung des Singletons verursachen. Im Testcode können Sie einen Anruf einleiten, sich Release.

Andere Tipps

An diesem Punkt glaube ich nicht, dass ich es wirklich betrachten würde ein Singleton mehr zu sein, ehrlich zu sein.

Insbesondere dann, wenn ein Client eine Singleton verwendet sind sie wirklich nicht gehen zu erwarten, dass sie darüber verfügen, und sie wären überrascht, wenn jemand anderes getan hat.

Was ist Ihre Produktion Code tun?

EDIT: Wenn Sie wirklich, wirklich diese Tests für die Einheit brauchen und nur für Unit-Tests (die in Bezug auf Design fragwürdig klingen, um ehrlich zu sein), dann könnte man immer mit der Feld mit Reflexion Geige . Es wäre schöner, um herauszufinden, ob es sollte wirklich ein Singleton sein oder ob es wirklich sein, obwohl Einweg -. Die beide sehr selten zusammen gehen

Singletons sollte nicht Einweg sein. Zeitraum. Wenn jemand anruft Entsorgen vorzeitig, wird Ihre Anwendung geschraubt, bis es neu gestartet wird.

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

  }

Wenn die Klasse IDisposable implementiert (wie Sie bedeuten es tut), dann rufen Sie einfach an x.Dispose ()

Sie können einen verschachtelten faul Singleton verwenden (Siehe hier ) mit einigen einfache Änderungen:

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

Denken Sie daran, ObjectDisposedException in allen öffentlichen Methoden / Eigenschaften des Objekts zu werfen, wenn sie entsorgt wurde.

Sie sollten auch, bieten eine Finalizerthread Methode für das Objekt, falls Entsorgen nicht aufgerufen. Sehen, wie man richtig implementieren IDisposable hier .

Für Unit-Tests können Sie eine „manuelle“ Instanz verwenden (aber man würde einen Weg braucht das Objekt zu instanziiert).

In Ihrem Fall wahrscheinlich sollten Sie besser die Fabrik Muster verwenden (Abstract / Methode - je nachdem, was das Beste für Ihren Fall ist)., Mit einem Singleton kombiniert

Wenn Sie testen möchten, ob die Singleton richtig der verwendeten Objekte angeordnet hat (in Unit-Test), dann die Fabrik-Methode verwenden, da sonst die Singletonmuster verwenden.

By the way, wenn Sie keinen Zugriff auf die Singleton-Quellcode haben, oder Sie sind nicht zu ändern es erlaubt, Sie besser zu einem anderen Singleton wickeln würde, und alle Extras, die Logik von der neuen (eher wie ein Proxy). Es klingt wie viel des Guten, aber es könnte eine praktikable Lösung sein.

Auch, um den Zugang kontrollieren zu können, eine Fabrik zur Verfügung stellen, und läßt die Kunden das neue Objekt erhalten nur dann, wenn das Objekt angeordnet worden ist.

Eine weitere Möglichkeit, eine Einweg Singleton zu machen Sandburg zu gebrauchen [Singleton] atribute für Ihre Klasse, dann Castle Rahmen übernimmt alle Einweg Singleton Objekte der Entsorgung

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top