C # Singleton Pattern и MEF - PullRequest
       3

C # Singleton Pattern и MEF

9 голосов
/ 26 января 2012

У меня есть вопрос по поводу шаблона Singleton и MEF. Я новичок в реализации плагинов MEF, и я не нашел ответа.

Можно ли предоставить только один экземпляр класса через реализованный MEF плагин?

Мой старый класс примерно такой:


  #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

Может ли кто-нибудь привести мне пример?

Ответы [ 2 ]

19 голосов
/ 26 января 2012

Да, это возможно.

По умолчанию MEF всегда будет возвращать один и тот же экземпляр класса при заполнении импорта.Так что технически вам не нужно ничего делать, если вы хотите, чтобы это был синглтон.Это то, что MEF называет общей политикой создания.

Если вы не хотите, чтобы импорт осуществлялся из одного и того же экземпляра, вам необходимо указать его либо в атрибутах, аналогично:

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

Или вы можете переопределить свой собственный CompositionContainer, чтобысоздаст NonShared экземпляры по умолчанию.

Обратите внимание, что вы также можете явно указать, что вы хотите использовать общую политику создания (синглтоны):

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

Но это не обязательно, так как Shared (singleton) уже является значением по умолчанию.

Вот ссылка на документацию MEF: http://mef.codeplex.com/wikipage?title=Parts%20Lifetime, которая объясняет то, о чем я только что говорил.Вы также можете найти блоги по этой теме, выполнив поиск: «Политика создания MEF».

0 голосов
/ 26 января 2012

Очень плохая практика!использовать статический конструктор: гарантированно будет выполнен ровно один раз

Обратите внимание, что для каждого создаваемого вами T CLR скопирует статические данные для нового T.

создаем синглтон для каждого типа T, который вы используете.

Лучший способ для синглтона - это что-то вроде этого:

public class Logger {
    public static readonly Logger Instace;

    static Logger() {
        Instace = new Logger();
    }
}
...