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 {
...
}
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; }
}
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");
}
}
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");
}
}
Note: When doing method exports, you are required to either provide a type or a string contract name, and cannot leave it blank.
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.