Hosting MEF in an application 在应用程序中寄宿MEF
Hosting MEF in an application involves creating an instance of the
CompositionContainer, adding Composable Parts to it, including the application host itself and then composing.
在应用程序中寄宿MEF涉及创建一个CompositionContainer的实例,向此实例添加可组合的部件,包括寄宿程序本身,然后进行组合.
Below are the steps involved with hosting.
下面是寄宿的步骤:
1. Create a host class. In the sample below we are using a console application, so the host is the Program class.
创建一个宿主类。在下面的示例中,我们将使用一个控制台程序,所以它的宿主类就是 Program类。
2. Add a reference to the System.ComponentModel.Composition assembly.
在工程中添加程序集System.ComponentModel.Composition的引用。
3. Add the following using statement: using System.ComponentModel.Composition;
在宿主类中添加using System.ComponentModel.Composition语句。
4. Add a Compose() method which creates an instance of the container and composes the host.
添加一个Compose方法来创建CompositionContainer的实例和组合宿主类。
5. Add a Run() method which calls Compose();
添加一个Run方法来调用Compose方法。
6. In the Main() method instantiate the host class.
在Main方法中实例化宿主类。
Note: For an ASP.NET or WPF application the host class is instantiated by the runtime making this step unnecessary.
备注:对于APS.net或者WPF应用程序来说,它们的宿主类是由运行环境本身来实例化的,所以第6步对于它们来说是多余的。
The code snippet below indicates how the code should look
下面的代码片段演示代码的样子:
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 void Run()
{
Compose();
}
private void Compose()
{
var container = new CompositionContainer();
container.ComposeParts(this);
}
}
Imports System.ComponentModel.Composition
Imports System.ComponentModel.Composition.Hosting
Imports System.Reflection
Imports System
Public Class Program
Public Shared Sub Main(ByVal args() As String)
Dim p As New Program()
p.Run()
End Sub
Public Sub Run()
Compose()
End Sub
Private Sub Compose()
Dim container = New CompositionContainer()
container.ComposeParts(Me)
End Sub
End Class
7. Define one or more exports which the host will import. In the code below we've defined an
IMessageSenderinterface. We've also defined an
EmailSender
Composable Part that exports an
IMessageSender
which it declares through the
[System.ComponentModel.Composition.Export]
attribute.
定义一个或多个用来导入宿主类的导出。在下面的代码中,我们已经定了一个IMessageSender接口,同时我们通过使用[System.ComponentModel.Composition.Export]特性定义了一个可组合的部件EmailSender来导出IMessageSender。
public interface IMessageSender
{
void Send(string message);
}
[Export(typeof(IMessageSender))]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine(message);
}
}
Public Interface IMessageSender
Sub Send(ByVal message As String)
End Interface
<Export(GetType(IMessageSender))>
Public Class EmailSender
Implements IMessageSender
Public Sub Send(ByVal message As String) Implements IMessageSender.Send
Console.WriteLine(message)
End Sub
End Class
8. Add properties to the host class for each import which are decorated with the
[System.ComponentModel.Composition.Import]
attribute. For example below is an import for
IMessageSender
that is added to the
Program
class.
对于每个导入,添加一个使用
[System.ComponentModel.Composition.Import]特性进行装饰的属性。例如Program类中添加一个IMessageSender类型的导入。
[Import]
public IMessageSender MessageSender { get; set; }
<Import()>
Public Property MessageSender() As IMessageSender
9. Add parts to the container. In MEF, there are several ways in which to do this. One way is by directly adding existing Composable Part instances, while a second, more common approach is through the use of catalogs, which we will mention after the section below.
添加部件到容器中。在MEF中,有多种方式执行此操作。第一种方式是直接添加现存的可组合部件的实例。而第二种方式,也是更常见的方式是通过使用目录,我们将在下节中提到。
Adding parts directly to the container
直接添加部件到容器中
In the
Compose()
method manually add each Composable Part by using the
ComposeParts()
extension method. In the example below, an instance of the
EmailSender
added to the container along with the current instance of the Program class which imports it.
在Compose()方法中,通过使用ComposeParts 扩展方法手动添加每个可组合的部件。在下面的示例中,EmailSender的实例以及导入它的Program类的实例都添加到了容器中。
private void Compose()
{
var container = new CompositionContainer();
container.ComposeParts(this, new EmailSender());
}
Private Sub Compose()
Dim container = New CompositionContainer()
container.ComposeParts(Me, New EmailSender())
End Sub
Adding to the container using an AssemblyCatalog
使用AssemblyCatalog(程序集目录)添加到容器
By using the catalog, the container handles creating parts automatically rather than them having to be added explicitly. To do this, create a catalog in the
Compose()
method. Next create a resolver off of the catalog and pass it to the container's constructor.
通过使用目录,容器可以自动处理部件的创建,而不必显示添加他们到容器。为了完成此工作,需要在Compose()
方法中创建一个目录。接下来创建一个目录的解析者并把它传递给容器的构造函数。
In the example below an
AssemblyCatalog
is created with the executing assembly passed into the constructor. We're not adding an instance of EmailSender as it it will be discovered in the catalog that was passed for the current assembly.
在下面的示例中,使用可执行程序集创建了一个程序集目录,并把它传递给了容器的构造函数。我们没有添加EmailSender的实例到容器中,因为它能在传递过来的目录的当前程序集中被发现。
private void Compose()
{
var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
Private Sub Compose()
Dim catalog = New AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())
Dim container = New CompositionContainer(catalog)
container.ComposeParts(Me)
End Sub
After following each of the above steps, the code should look as shown below.
依照上面的每一步之后,代码看起来应该想下面这个样子。
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
using System;
public class Program
{
[Import]
public IMessageSender MessageSender { get; set; }
public static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
public void Run()
{
Compose();
MessageSender.Send("Message Sent");
}
private void Compose()
{
AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
}
public interface IMessageSender
{
void Send(string message);
}
[Export(typeof(IMessageSender))]
public class EmailSender : IMessageSender
{
public void Send(string message)
{
Console.WriteLine(message);
}
}
Imports System.ComponentModel.Composition
Imports System.ComponentModel.Composition.Hosting
Imports System.Reflection
Imports System
Public Class Program
<Import()>
Public Property MessageSender() As IMessageSender
Public Shared Sub Main(ByVal args() As String)
Dim p As New Program()
p.Run()
End Sub
Public Sub Run()
Compose()
MessageSender.Send("Message Sent")
End Sub
Private Sub Compose()
Dim catalog As New AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())
Dim container = New CompositionContainer(catalog)
container.ComposeParts(Me)
End Sub
End Class
Public Interface IMessageSender
Sub Send(ByVal message As String)
End Interface
<Export(GetType(IMessageSender))>
Public Class EmailSender
Implements IMessageSender
Public Sub Send(ByVal message As String) Implements IMessageSender.Send
Console.WriteLine(message)
End Sub
End Class
When the above code is compiled and executed, the application will be composed with its
IMessageSenderimport. The
Send()
method will then be called which will output "Message Sent" on the console.