.net instance - Singleton monouso in C#





dofactory java (8)


Per i test unitari è possibile utilizzare un'istanza "manuale" (ma è necessario un modo per creare un'istanza dell'oggetto).

Nel tuo caso, probabilmente dovresti usare meglio il pattern factory (abstract / method - a seconda di quale sia il migliore per il tuo caso), combinato con un singleton.

Se si desidera verificare se il singleton è stato disposto correttamente rispetto agli oggetti utilizzati (in unit test), utilizzare il metodo Factory, altrimenti utilizzare il modello singleton.

A proposito, se non si ha accesso al codice sorgente singleton o non si è autorizzati a modificarlo, è meglio inserirlo in un altro singleton e fornire tutta la logica da quella nuova (più come un proxy). Sembra eccessivo, ma potrebbe essere una soluzione praticabile.

Inoltre, per essere in grado di controllare l'accesso ad esso, fornire una fabbrica e lasciare che i client ottengano il nuovo oggetto solo se l'oggetto non è stato eliminato.

Ho un singleton che usa la "static Readonly T Instance = new T ();" modello. Tuttavia, mi sono imbattuto in un caso in cui T è usa e getta, e in realtà deve essere smaltito per i test unitari. Come posso modificare questo modello per supportare un singleton usa e getta?

L'interfaccia che vorrei è qualcosa di simile:

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.

Nota: lo schema deve essere sicuro per i thread, ovviamente.

Modifica : per lo scopo del codice di produzione, questo è un vero singleton. Il fatto è che blocca alcuni file, quindi per la pulizia dei test unitari dobbiamo smaltirlo.

Preferirei anche uno schema che possa essere riutilizzato, se possibile.




I gemelli non dovrebbero essere eliminabili. Periodo. Se qualcuno chiama Dispose prematuramente, l'applicazione viene avvitata finché non si riavvia.




Contrassegnare la Release come internal e utilizzare l'attributo InternalsVisibleTo per esporla solo al gruppo di prova dell'unità. Puoi farlo o, se sei diffidente nei confronti di qualcuno del tuo stesso assembly, puoi contrassegnarlo come private e accedervi utilizzando la reflection.

Utilizzare un finalizzatore nel singleton che chiama il metodo Dispose nell'istanza Singleton.

Nel codice di produzione, solo lo scarico di un AppDomain causerà l'eliminazione del singleton. Nel codice di prova, è possibile avviare una chiamata per Release .




A quel punto non credo che lo considererei davvero un singleton, a dire il vero.

In particolare, se un cliente utilizza un singleton, non si aspetterebbe che debbano smaltirlo e sarebbero sorpresi se lo facesse qualcun altro.

Cosa farà il tuo codice di produzione?

EDIT: Se davvero, davvero bisogno di questo per i test unitari e solo per i test unitari (che suona discutibile in termini di design, per essere sinceri) allora si potrebbe sempre giocare con il campo usando la riflessione. Sarebbe più bello capire se dovesse essere davvero un singleton o se debba essere effettivamente usa e getta, i due raramente vanno insieme.




Un'altra opzione per creare un Singleton usa e getta è usare l'attributo [Singleton] di SandCastle per la tua classe, quindi Castle framework si occupa di eliminare tutti gli oggetti Singleton monouso




Potresti usare un singleton pigro annidato (vedi qui ) con alcune semplici modifiche:

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

Ricordarsi di lanciare ObjectDisposedException in tutti i metodi / proprietà pubbliche dell'oggetto se è stato eliminato.

Dovresti anche fornire un metodo finalizzatore per l'oggetto, nel caso in cui non venga richiamato Dispose. Scopri come implementare correttamente IDisposable qui .




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

  }



Classe statica: -

  1. Non è possibile creare l'istanza della classe statica.

  2. Caricato automaticamente da .NET Framework Common Language Runtime (CLR) quando viene caricato il programma o lo spazio dei nomi contenente la classe.

  3. La classe statica non può avere un costruttore.

  4. Non possiamo passare la classe statica al metodo.

  5. Non possiamo ereditare la classe statica in un'altra classe statica in C #.

  6. Una classe con tutti i metodi statici.

  7. Prestazioni migliori (i metodi statici sono legati al tempo di compilazione)

Singleton:-

  1. È possibile creare un'istanza dell'oggetto e riutilizzarla.

  2. L'istanza Singleton viene creata per la prima volta quando l'utente lo richiede.

  3. La classe Singleton può avere un costruttore.

  4. È possibile creare l'oggetto della classe Singleton e passarlo al metodo.

  5. La classe di Singleton non dice alcuna restrizione dell'eredità.

  6. Possiamo disporre gli oggetti di una classe singleton ma non di una classe statica.

  7. I metodi possono essere ignorati.

  8. Può essere pigro caricato quando necessario (le classi statiche sono sempre caricate).

  9. Possiamo implementare l'interfaccia (la classe statica non può implementare l'interfaccia).





c# .net singleton dispose