[MEF程序设计指南]定义可以组合的部件和契约

Defining Composable Parts and Contracts

定义可组合的部件和契约

Composable Parts 可组合的部件

A Composable Part is a composable unit within MEF. Composable Parts export services that other Composable Parts need, and import services from other Composable Parts. In the MEF programming model, Composable Parts are attributed with the   System.ComponentModel.Composition.Import  and [System.ComponentModel.Composition.Export]  attribute in order to declare their exports and imports. A Composable Part should contain at least one export. Composable Parts are either added to the container explicity or created through the use of catalogs. The default catalogs that MEF ship with identify Composable Parts through the presence of an export attribute.
 
可组合部件是MEF内部的可组合单元。可组合部件导出其他可组合部件需要的服务,并且也可以导入其他可组合部件。在MEF的编程模型中,可组合部件使用 System.ComponentModel.Composition.ImportSystem.ComponentModel.Composition.Export特性来声明它们的导出和导入。可组合部件应该至少包含一个导出。可组合部件既可以显示地添加到容器,也可以使用目录来创建。MEF中附带的默认目录通过export特性的存在来标识可组合部件。

 

Contracts 契约

Composable Parts do not directly depend on one another, instead they depend on a contract, which is a string identifier. Every export has a contract, and every import declares the contract it needs. The container uses the contract information to match up imports to exports. If no contract is specified, MEF will implicitly use the fully qualified name of the type as the contract. If a type is passed, it will also use the fully qualified name.  
 
可组合部件不直接依赖于另外一个,相反他们依赖于字符串标识的契约。每个导出都有一个契约,同时每个导入声明了它们需要的契约。容器使用契约信息来匹配导入和导出。如果没有指名契约,MEF会隐示地使用类型的全限定名称来作为契约。如何传递一个类型,同样默认使用全限定名称来作为契约。

Note: By default a type should be passed for a contract, and not a string. Although contracts can be an arbitrary string this can lead to ambiguity. For example "Sender" might overlap with another implementation of "Sender" in a different library. For this reason if you do need to specify a string constract, it is recommend that contract names should be qualified with a namespace that includes the Company Name for example "Contoso.Exports.Sender".
 
备注:默认情况下,契约可能被误认为是类型,而不是字符串。然而契约可以是任意字符串,这可能会导致歧义。例如,“Sender”可能与另外一个不同库中的Sender实现重叠。因此如果你要指定一个字符串契约,推荐使用包含公司名称的命名空间作为契约名称,例如:"Contoso.Exports.Sender"。

In the code snippet below, all export contracts are equivalent.
在下面的代码片段中,所有导出的契约都是相同的。

namespace MEFSample 
{
  [Export]
  public class Exporter {...}

  [Export(typeof(Exporter))]
  public class Exporter1 {...}

  [Export("MEFSample.Exporter")]
  public class Exporter2 {...}
}
Namespace MEFSample
    <Export()>
    Public Class Exporter
        ... 
    End Class
    <Export(GetType(Exporter))> 
    Public Class Exporter1
        ... 
    End Class
    <Export("MEFSample.Exporter")>
    Public Class Exporter2
        ... 
    End Class
End Namespace

 Interface / Abstract contracts 接口/抽象类契约

A common pattern is for a Composable Part to export an interface or an abstract type contract rather than a concrete type. This allows the importer to be completely decoupled from the specific implementation of the export it is importing resulting in a separation of concerns. For example below you can see there are two sender implementations that both export   IMessageSender. The   Notifier  class imports a collection of IMessageSender  which it invokes in its   Send()  method. New message senders can now easily be added to the system.
 
通常模式下,可组合部件导出接口或者抽象类型的契约,而不是具体类型。这允许导入者脱离具体的导出,从而使关注点分离。例如下面你可以看见有2个sender实现都导出了IMessageSender契约。Notifier类导入一个 IMessageSender集合并且调用每个导入的Send方法。现在新的信息Sender类可以很容易被添加到这个系统。

 
  [Export(typeof(IMessageSender))]
  public class EmailSender : IMessageSender {
    ...
  }

  [Export(typeof(IMessageSender))]  
  public class TCPSender : IMessageSender {
    ...
  }

  public class Notifier {
    [ImportMany]
    public IEnumerable<IMessageSender> Senders {get; set;}
    public void Notify(string message) {
      foreach(IMessageSender sender in Senders) 
        sender.Send(message);
    } 
  }

<Export(GetType(IMessageSender))> 
Public Class EmailSender
    Implements IMessageSender
    ... 
End Class

<Export(GetType(IMessageSender))> 
Public Class TCPSender
    Implements IMessageSender
    ... 
End Class

Public Class Notifier
    <ImportMany()>
    Public Property Senders() As IEnumerable(Of IMessageSender) 
    Public Sub Notify(ByVal message As String) 
        For Each sender As IMessageSender In Senders
            sender.Send(message) 
        Next sender
    End Sub
End Class

Contract Assemblies

A common pattern when building extensible applications with MEF is to deploy a contract assembly. A contract assembly is simply an assembly which contains contract types that extenders can use for extending your app. Commonly these will be interfaces, but they may be abstract classes. Additonally contract assemblies will likely contain metadata view interfaces that importers will use, as well as any custom MEF export attributes.
Note: You must specify the specific interface type (IMessageSender) being exported otherwise the type (EmailSender) itself will be exported.
 
通常模式下,当使用MEF创建可扩展应用程序时可以部署契约程序集。契约程序集是一个包含契约类型可以用来扩展你的应用的简单程序集。通常他们是接口,除此之外也可能是抽象类。此外,契约程序集可能会包含导入者使用的元数据视图接口,或者任何自定义的MEF导出属性类。
 
备注:你必须指明导出的具体接口类型(IMessageSender),否则类型自身(EmailSender)会被导出。

Last edited Aug 10, 2010 at 1:09 AM by haveriss, version 34

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值