Declaring Exports

Composable Parts declare exports through the [System.ComponentModel.Composition.ExportAttribute] attribute. In MEF there are several different ways to declare exports including at the Part level, and through Properties and Methods.

Composable Part exports

A Composable Part level export is used when a Composable Part needs to export itself. In order for a Composable Part to export itself, simply decorate the Composable Part with a [System.ComponentModel.Composition.ExportAttribute] attribute as is shown in the code snippet below.

[Export]
public class SomeComposablePart {
  ...
}
<Export()>
Public Class SomeComposablePart
    ... 
End Class

Property exports

Parts can also export properties. Property exports are advantageous for several reasons.
  • They allow exporting sealed types such as the core CLR types, or other third party types.
  • They allow decoupling the export from how the export is created. For example exporting the existing HttpContext which the runtime creates for you.
  • They allow having a family of related exports in the same Composable Part, such as a DefaultSendersRegistry Composable Part that exports a default set of senders as properties.
For example you might have a Configuration class that exports an integer with a "Timeout" contract as in the example below.

  public class Configuration
  {
    [Export("Timeout")]
    public int Timeout
    {
      get { return int.Parse(ConfigurationManager.AppSettings["Timeout"]); }
    }
  }
  [Export]
  public class UsesTimeout
  {
    [Import("Timeout")]
    public int Timeout { get; set; }
  }
Public Class Configuration
    <Export("Timeout")>
    Public ReadOnly Property Timeout() As Integer
        Get
            Return Integer.Parse(ConfigurationManager.AppSettings("Timeout"))
        End Get
    End Property
End Class
<Export()>
Public Class UsesTimeout
    <Import("Timeout")>
    Public Property Timeout() As Integer
End Class

Method exports

A method export is where a Part exports one its methods. Methods are exported as delegates which are specified in the Export contract. Method exports have several benefits including the following.
  • They allow finer grained control as to what is exported. For example, a rules engine might import a set of pluggable method exports.
  • They shield the caller from any knowledge of the type.
  • They can be generated through light code gen, which you cannot do with the other exports.
Note: Method exports may have no more than 4 arguments due to a framework limitation.

In the example below, the MessageSender class exports its Send method as an Action<string> delegate. The Processor imports the same delegate.

  public class MessageSender
  {
    [Export(typeof(Action<string>))]
    public void Send(string message)
    {
      Console.WriteLine(message);
    }
  }

  [Export]
  public class Processor
  {
    [Import(typeof(Action<string>))]
    public Action<string> MessageSender { get; set; }

    public void Send()
    {
      MessageSender("Processed");
    }
  }

Public Class MessageSender
    <Export(GetType(Action(Of String)))> 
    Public Sub Send(ByVal message As String) 
        Console.WriteLine(message) 
    End Sub
End Class

<Export()>
Public Class Processor
    <Import(GetType(Action(Of String)))> 
    Public Property MessageSender() As Action(Of String) 

    Public Sub Send()
        MessageSender()("Processed")
    End Sub
End Class

You can also export and import methods by using a simple string contract. For example below the "Sender" contract is used.

  public class MessageSender
  {
    [Export("MessageSender")]
    public void Send(string message)
    {
      Console.WriteLine(message);
    }
  }

  [Export]
  public class Processor
  {
    [Import("MessageSender")]
    public Action<string> MessageSender { get; set; }

    public void Send()
    {
      MessageSender("Processed");
    }
  }
Public Class MessageSender
    <Export("MessageSender")>
    Public Sub Send(ByVal message As String) 
        Console.WriteLine(message) 
    End Sub
End Class

<Export()>
Public Class Processor
    <Import("MessageSender")>
    Public Property MessageSender() As Action(Of String) 

    Public Sub Send()
        MessageSender()("Processed")
    End Sub
End Class

Note: When doing method exports, you are required to either provide a type or a string contract name, and cannot leave it blank.

Inherited Exports

MEF supports the ability for a base class / interface to define exports which are automatically inherited by implementers. This is ideal for integration with legacy frameworks which want to take advantage of MEF for discovery but do not want to require modifying existing customer code. In order to provide this capability use the System.ComponentModel.Composition.InheritedExportAttribute. For example below ILogger has an InheritedExport. Logger implements ILogger thus it automatically exports ILogger.

[InheritedExport]
public interface ILogger {
  void Log(string message);
}

public class Logger : ILogger {
  public void Log(string message);
}
<InheritedExport()>
Public Interface ILogger
    Sub Log(ByVal message As String) 
End Interface

Public Class Logger
    Implements ILogger
    Public Sub Log(ByVal message As String) Implements ILogger.Log

    End Sub

End Class

Discovering non-public Composable Parts

MEF supports discovery of public and non-public Parts. You don't need to do anything to enable this behavior. Please note that in medium/partial trust environments (including Silverlight) non-public composition will not be supported.

Last edited Aug 9, 2010 at 6:12 PM by haveriss, version 35

Comments

marcoslimagon Jul 20, 2012 at 3:16 PM 
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System;

public class Program
{
public static void Main(string[] args)
{
Program p = new Program();
p.Run();
}

public CompositionContainer container = null;

/// <summary>
/// Set the container global variable
/// </summary>
private void Compose()
{
AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());

container = new CompositionContainer(catalog);
}

public void Run()
{
Compose();

// Calling a method without use interfaces. More flexible and "easy to use".
// Useful for plugins
foreach (var view in container.GetExports<Func<string, bool>>("MessageSender"))
{
Console.WriteLine(view.Value("PUC-Campinas"));
}

Console.ReadKey();
}


}

public class MessageSender
{
[Export("MessageSender")]
public bool Send(string message)
{
Console.WriteLine(message);
return true;
}
}

aidesigner Jul 6, 2011 at 9:42 PM 
Does method/property exports actual create an instance of the class when the corresponding import is satisfied. If not what happens if the method utilizes a private member variable of the class. Basically it is looking like method/property exports must adhere to the rules of a static method/property.

aaronh Feb 15, 2011 at 10:01 PM 
diegum, you could always create a proxy class that exposes the MEF attributes. Your proxy would serve as the middle-man and route the calls to the code base that doesn't belong to you.

ploeh Sep 15, 2010 at 2:25 PM 
@diegum: You can go and vote for that feature here: http://mef.uservoice.com/forums/75901-general/suggestions/1056205-support-composition-without-attributes?ref=title

diegum Jun 14, 2010 at 9:54 PM 
Is there any way to declare exports and imports through configuration files instead of attributes? It would help a lot as sometimes we don't own the code in order to decorate its classes or properties. It's also good to avoid ties between our code base and MEF if tomorrow we'd like to get the same result with another technology.

ajay555 Apr 10, 2010 at 12:28 PM 
One of the comment posted in my earlier example of MEF was what if we have two implementations of the same interface and we need to decide at run time which implementation to use. I have posted another blog which gives the example of usage of ExportMetadata for handing this scenario.

http://ppsinfo.blogspot.com/2010/04/managed-extensibility-framework-mef.html

cesnek Apr 2, 2010 at 2:20 PM 
Can MEF create instance of my class (with imports) - without any others class imports my class.
Now MEF dont create my classes without other classes references.

dvanderboom Sep 22, 2009 at 7:16 PM 
How do I force a property export to require CreationPolicy.Shared? The PartCreationPolicyAttribute would be useful for this, but currently can only be applied to a class. I'd like to export the container itself, so it can be accessed from other modules.

nblumhardt Jul 7, 2009 at 4:41 PM 
Thanks Daniel, fixed now.

danielearwicker May 13, 2009 at 6:06 PM 
"The OrderProcessor imports the same delegate in its constructor." Wrong class name, wrong importing technique. Score: zero out of two!