Posterous theme by Cory Watilo

The difference between typed and named imports/exports in MEF

The key principal for MEF if the definition of exports (the parts which will be injected into an application at run-time) and imports (design-time defined points in the application which can be extended at run-time).


These are defined using declarative programming with the help of the ExportAttribute and ImportAttribute attributes and each comes with their own restrictions


  • The ImportAttribute can be used with fields, properties and parameters. The ability to define parameters as imports enabled MEF to be used for constructor parameter injection. In order to do this you will have to use the special attribute ImportingConstructor to let the framework know you want to do constructor composition.
  • The ExportAttribute can be used with with classes, fields, properties and methods. Notice that while methods can be defined as exports, there’s no way to define a method as an import. The framework uses a little trick where you define the import as a property where the type is a delegate (such as Action or Func). This enables you to export a real method and import it wrapped in a delegate.

One thing that both attributes have in common is the exact same constructor overloads. You have the option to either use a type or a string name to define the import/export contract.


So what’s the difference between the two overloads? The fact is that there are no differences between the two. The framework is designed to use string contracts, so when you provide a type in either of the attributes it will be converted to a string, using the fully qualified name of the type (it does so by calling CompositionServices.GetContractName).


The main reason for this is to be able to use MEF in dynamic languages as well as with statically typed languages.

This means that


  • [Import(typeof(IFoo))]
  • [Import(“Namespace.Hierachy.IFoo”)]

Are identical as far as MEF if concerned (assuming of course that the IFoo interface is located in the Namespace.Hierachy namespace). The recommendation from the MEF team is to use the strongly typed overload when ever possible and I agree because it will help reduce problems brought on by spelling mistakes and it’s also compatible with refactoring.


However there are scenarios when using the string overloads are justifiable and even required. This is true when ever you are working with a contract which you do not have control over and yet you want to target specific exports.


For example what would you do when you wanted to import/export a primitive (int, long, string and so on) or perhaps something as common as a user control? Imagine the following example


1:  public class Foo
2:  {
3:      [Import(typeof(int))]
4:      public int Timeout { get; set; }
5:  }

Just using Import(typeof(int)) would make the framework try to inject all Export(typeof(int)) which it has found in the part catalogs. Not only would this result in an exception since Timeout is not a collection, but even if it was a collection we could get very unexpected behavior.


So to get around this you can then use a named import/export pair, thus creating a unique contract even though the type is widely used.


1:  public class Foo
2:  {
3:      [Import("Foo.Timeout")]
4:      public int Timeout { get; set; }
5:  }

This enables you to create an export, targeted for a specific import (“Foo.Timeout”) even though the type of the contract is used in many places.


I hope this brings some light on import/export contracts when using MEF.