10

I have a question about the Singleton Pattern and MEF. I'm new in implementing MEF Plugins and I haven't found an answer.

Is it possible to provide only one instance of a class through a MEF implemented Plugin?

My old class is something like this:


  #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

Can someone provide me an example?

Gilles
  • 5,269
  • 4
  • 34
  • 66
subprime
  • 1,217
  • 8
  • 20
  • 34
  • 1
    possible duplicate of [Does MEF lend any value to the Singleton pattern?](http://stackoverflow.com/questions/4484619/does-mef-lend-any-value-to-the-singleton-pattern) – IAbstract Jan 25 '12 at 22:43
  • Sorry, not related to the question, but looks like you’re unnecessarily reimplementing `Lazy`. The extraneous lines of code! – binki Mar 11 '16 at 17:22

2 Answers2

22

Yes it is possible to do so.

By default, MEF will always return the same instance of a class when it fill your imports. So technically you do not have to do anything if you want it to be a singleton. This is what MEF calls a Shared Creation Policy.

If you do not want your imports to come from the same instance, you need to specify it, either in your attributes likewise:

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

Or you can override your own CompositionContainer so that will create NonShared instances by default.

Note that you can also explicitly specify that you want a Shared Creation Policy (singletons):

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

But it is not necessary as Shared (singleton) is already the default value.

Here is a link to MEF's documentation : http://mef.codeplex.com/wikipage?title=Parts%20Lifetime which explains what I just talked about. You can also find blogs on the subject by searching for : "MEF Creation Policy".

Gilles
  • 5,269
  • 4
  • 34
  • 66
  • Gilles is absolutely right about the way MEF will behave with respect to the CreationPolicy. Just thought I'd point out that the one-instance-guarantee you get with the singleton pattern isn't as strictly enforced here since someone can still new-up another instance outside of MEF. – MatrixManAtYrService Jul 02 '13 at 17:55
0

Very bad practice ! use static constructor: guaranteed to be executed exactly once

Please note that for each T that you create, the CLR will copy the static data for the new T.

So you are creating a singleton per T type that you use.

The best way for singleton is something like this:

public class Logger {
    public static readonly Logger Instace;

    static Logger() {
        Instace = new Logger();
    }
}
Yuck
  • 49,664
  • 13
  • 105
  • 135
Mudx
  • 605
  • 5
  • 5
  • Hi, thanks for very quikly answer but how i can use it with MEF? – subprime Jan 25 '12 at 21:33
  • You can use this with MEF. Just MEF everything up like you normally would and then when MEF FIRST initializes the class the static constructor is invoked. – Dan But Jan 24 '14 at 23:39