Use MEF to allow only 2 instances at max per application

Mar 27, 2013 at 10:21 AM
Edited Mar 27, 2013 at 10:22 AM
I am using MEF as an IOC in my application. I found myself stuck in a situation where I need exactly two instance at a time for a class in my application (across all threads). I thought it would be easy just by adding export attribute twice with different container name and then using that container name to create two instances.
[Export("Condition-1",typeof(MyClass)]
[Export("Condition-2",typeof(MyClass)]
[PartCreationPolicy(System.ComponentModel.Composition.CreationPolicy.Shared)]
public class MyClass  {   }
And then get export as
Container.GetExport<MyClass>("Condition-1").Value
Container.GetExport<MyClass>("Condition-2").Value
But this trick did not work. CreationPolicy is ignoring the ContractName and is returning one instance no matter what contract name i use in GetExport. I finally able to solve my problem by using CompsositionBatch
cb.AddExportedValue<MyClass>("Condition-1",new MyClass());
cb.AddExportedValue<MyClass>("Condition-2",new MyClass());
But my question is, Why am I not able to get different instances on the basis of Contract Name. Is it right that Contract name does not matter if CreationPolicy is shared?
Mar 28, 2013 at 12:36 PM
Hi there,

Creation policy (e.g. sharing) applies to parts, while one part may have many exports. This is just how the MEF component model works - in most situations this turns out to be useful.

To achieve what you want in a more MEF-like way:
  1. Don't make MyClass a part at all:
public class MyClass { }
  1. Create a separate class that holds and exports the two instances as properties:
public class MyClassConfig
{
   MyClass _inst1 = new MyClass();
   MyClass _inst2 = new MyClass();

   [Export("Condition-1")]
   public MyClass Inst1 { get { return _inst1; } }

   [Export("Condition-2")]
   public MyClass Inst2 { get { return _inst2; } }
}
This is the basic approach, anyway - you can tinker with MyClassConfig to implement lazy construction etc. if this is needed.

Hope this simplifies things!
Nick