2012-01-25 18 views
9

Tengo una pregunta sobre Singleton Pattern y MEF. Soy nuevo en la implementación de complementos MEF y no he encontrado una respuesta.C# Singleton Pattern y MEF

¿Es posible proporcionar solo una instancia de una clase a través de un complemento implementado por MEF?

Mi vieja clase es algo como esto:


    #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 

Puede alguien dar un ejemplo?

+1

posible duplicado de [¿MEF da algún valor al patrón Singleton?] (Http://stackoverflow.com/questions/4484619/does-mef-lend-any-value-to-the-singleton-pattern) – IAbstract

+0

Lo siento, no está relacionado con la pregunta, pero parece que estás innecesariamente reimplementando 'Lazy '. ¡Las líneas de código extrañas! – binki

Respuesta

18

Sí, es posible hacerlo.

Por defecto, MEF siempre devolverá la misma instancia de una clase cuando complete sus importaciones. Entonces, técnicamente no tienes que hacer nada si quieres que sea un singleton. Esto es lo que MEF llama una Política de Creación Compartida.

Si no desea que sus importaciones provengan de la misma instancia, es necesario especificar que, ya sea en sus atributos asimismo:

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

O puede anular su propia CompositionContainer de manera que se cree instancias no compartidos por defecto.

Tenga en cuenta que también se puede especificar explícitamente que quiere una política de creación compartida (únicos):

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

Pero no es necesario ya compartida (Singleton) ya es el valor predeterminado.

Aquí hay un enlace a la documentación de MEF: http://mef.codeplex.com/wikipage?title=Parts%20Lifetime que explica de lo que acabo de hablar. También puede encontrar blogs sobre el tema buscando: "Política de creación MEF".

+0

gracias! ¡Funciona! – subprime

+0

Gilles tiene toda la razón sobre la forma en que MEF se comportará con respecto a CreationPolicy. Solo pensé en señalar que la garantía de una instancia que obtienes con el patrón singleton no se aplica tan estrictamente aquí, ya que alguien puede crear otra instancia fuera del MEF. – MatrixManAtYrService

+0

@MatrixManAtYrService ¡buen punto! – Gilles

1

¡Muy mala práctica! usar constructor estático: garantizada para ser ejecutado exactamente una vez

Tenga en cuenta que para cada T que se crea, el CLR copiará los datos estáticos para el nuevo T.

Así que está creando un singleton por tipo de T que utilice.

La mejor manera de Singleton es algo como esto:

public class Logger { 
    public static readonly Logger Instace; 

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

Hola, gracias por la respuesta muy rápida, pero ¿cómo puedo usarlo con MEF? – subprime

+0

Puede usar esto con MEF. Solo MEF todo como lo haría normalmente y luego, cuando MEF FIRST inicializa la clase, se invoca el constructor estático. –