2012-01-25 14 views
9

Ho una domanda su Singleton Pattern e MEF. Sono nuovo nell'implementazione dei plugin MEF e non ho trovato una risposta.C# Singleton Pattern e MEF

È possibile fornire solo un'istanza di una classe tramite un plugin implementato da MEF?

mia vecchia classe è qualcosa di simile:


    #region Singleton 
    /// 
    /// This class provide a generic and thread-safe interface for Singleton classes. 
    /// 
    /// The specialized singleton which is derived 
    /// from SingletonBase<T> 
    public abstract class Base where T : Base 
    { 
    /* the lock object */ 
    private static object _lock = new object(); 

    /* the static instance */ 
    private static T _instance = null; 
    /// 
    /// Get the unique instance of . 
    /// This property is thread-safe! 
    /// 
    public static T Instance 
    { 
     get 
     { 
     if (_instance == null) 
     { 
      lock (_lock) 
      { 
      if (_instance == null) 
      { 
       /* Create a object without to use new (where you need a public ctor) */ 
       object obj = FormatterServices.GetUninitializedObject(typeof(T)); 
       if (obj != null) // just 4 safety, but i think obj == null shouldn't be possible 
       { 
       /* an extra test of the correct type is redundant, 
       * because we have an uninitialised object of type == typeof(T) */ 
       _instance = obj as T; 
       _instance.Init(); // now the singleton will be initialized 
       } 
      } 
      } 
     } 
     else 
     { 
      _instance.Refresh(); // has only effect if overridden in sub class 
     } 
     return _instance; 
     } 
    } 


    /// 
    /// Called while instantiation of singleton sub-class. 
    /// This could be used to set some default stuff in the singleton. 
    /// 
    protected virtual void Init() 
    { } 

    /// 
    /// If overridden this will called on every request of the Instance but 
    /// the instance was already created. Refresh will not called during 
    /// the first instantiation, for this will call Init. 
    /// 
    protected virtual void Refresh() 
    { } 
    } 
    #endregion 

    #region class 
    public class xy : Base 
    { 
    private bool run; 

    public xy() 
    { 
     this.run = false; 
    } 

    public bool isRunning() 
    { 
     return this.run; 
    } 

    public void start() 
    { 
     // Do some stuff 
     this.run = true; 
    } 
    } 
    #endregion 

Qualcuno mi può fornire un esempio?

+1

possibile duplicato di [Fa MEF presta qualsiasi valore al modello Singleton?] (Http://stackoverflow.com/questions/4484619/does-mef-lend-any-value-to-the-singleton-pattern) – IAbstract

+0

Spiacente, non relativo alla domanda, ma sembra che tu stia inutilmente reimplementando 'Lazy '. Le linee estranee di codice! – binki

risposta

18

Sì, è possibile farlo.

Per impostazione predefinita, MEF restituirà sempre la stessa istanza di una classe quando riempie le importazioni. Quindi tecnicamente non devi fare nulla se vuoi che sia un singleton. Questo è ciò che MEF chiama una politica di creazione condivisa.

Se non si desidera che le importazioni provengono dalla stessa istanza, è necessario specificare che, sia nei tuoi attributi allo stesso modo:

[Import(RequiredCreationPolicy = CreationPolicy.NonShared)] 
public MyClass : IMyInterface 

Oppure si può ignorare il proprio CompositionContainer in modo che sarà creare istanze non condivisa per impostazione predefinita.

Si noti che è possibile anche in modo esplicito specificare che si desidera condiviso politica di creazione (single):

[Import(RequiredCreationPolicy = CreationPolicy.Shared)] 
public MyClass : IMyInterface 
{ 
    public MyClass() { } // you can have a public ctor, no need to implement the singleton pattern 
} 

Ma non è necessario in quanto condivisa (Singleton) è già il valore di default.

Ecco un collegamento alla documentazione di MEF: http://mef.codeplex.com/wikipage?title=Parts%20Lifetime che spiega di cosa ho appena parlato. Puoi anche trovare blog sull'argomento cercando: "Politica di creazione di MEF".

+0

grazie! Funziona! – subprime

+0

Gilles ha assolutamente ragione riguardo al modo in cui MEF si comporterà rispetto alla CreationPolicy. Ho solo pensato di far notare che la garanzia a una sola istanza che si ottiene con il modello di singleton non è applicata in modo così rigoroso da quando qualcuno può ancora creare un'altra istanza al di fuori di MEF. – MatrixManAtYrService

+0

@ MatrixManAtYrService buon punto! – Gilles

1

Pessima pratica! utilizzare costruttore statico: garantito da eseguire una sola volta

Si prega di notare che per ogni T che si crea, il CLR copierà i dati statici per il nuovo T.

Quindi si sta creando un singleton per il tipo T che si utilizza.

Il modo migliore per Singleton è qualcosa di simile:

public class Logger { 
    public static readonly Logger Instace; 

    static Logger() { 
     Instace = new Logger(); 
    } 
} 
+0

Ciao, grazie per la risposta molto tranquillamente ma come posso usarlo con MEF? – subprime

+0

È possibile utilizzare questo con MEF. Solo MEF funziona come faresti normalmente e poi quando MEF FIRST inizializza la classe viene richiamato il costruttore statico. –