声明导入
组成部件声明导入[System.ComponentModel.Composition.ImportAttribute]特性。跟导出类似,有几个不同的方法即是通过字段,属性和构造函数。
属性导入
为了导入一个属性值,用[System.ComponentModel.Composition.ImportAttribute]声明属性。例如下面的代码片段导入一个IMessageSender
class Program { [Import] public IMessageSender MessageSender { get; set; } }
构造函数参数
你也可以通过构造函数的参数指定导入。这意味着不必给每个导入添加属性,你只需要为导入给构造函数添加参数。为了使用这个,按照下面的步骤进行:
- 添加一个[System.ComponentModel.Composition.ImportingConstructorAttribute] 特性到要被MEF使用的构造函数。
- 为每个导入添加参数到构造函数。
例如下面的代码在Program类的构造函数导入一个message sender
class Program { [ImportingConstructor] public Program(IMessageSender messageSender) { ... } }
参数导入
有几个不同的方法在构造函数定义导入
1、隐式导入-默认容器会使用参数的类型去识别契约。例如在下面的借代码,IMessageSender契约会被使用。
class Program { [ImportingConstructor] public Program(IMessageSender messageSender) { } }
2、显式导入-如果你想要指定被导入的契约,添加[System.ComponentModel.Composition.ImportAttribute]特性到参数。
字段导入
MEF也支持直接导入字段值。
class Program { [Import] private IMessageSender _messageSender; }
注意:注意导入或导出私有成员(字段,属性和方法)当在完全信任状态下支持,在中间/局部信息状态可能有问题。
可选择导入
MEF允许你指定一个导入是可选的。当你允许这个,如果它是有效的容器会装备这个导出,否则它会设置导入是Default(T).为了使一个导入可选,在导入里设置AllowDefault=true,像下面一样:
[Export] public class OrderController { private ILogger _logger; [ImportingConstructor] public OrderController([Import(AllowDefault=true)] ILogger logger) { if(logger == null) logger = new DefaultLogger(); _logger = logger; } }
OrderController可选导入logger。如果logger不存在,它会设置private _logger为DefaultLogger 实例,否则它会使用导入的logger。
导入集合
除了单独导入外,你可以用ImportMany特性导入集合。这意味着所有指定契约的实例会从容器中导入。
MEF部件也可以支持重构。这意味着在容器里新的导出变得可行,集合在新设置里被自动更新。例如下面的Notifier类导入一个IMessageSender集合。这意味着如果有3个IMessageSender导出在容器里有效,在运行期间他们会被存放到Senders属性里。
public class Notifier { [ImportMany(AllowRecomposition=true)] public IEnumerable<IMessageSender> Senders {get; set;} public void Notify(string message) { foreach(IMessageSender sender in Senders) { sender.Send(message); } } }
IPartImportsSatisfiedNotification
在一些情形下当MEF为你的类实例完成导入过程时你的类被通知对你很重要。如果是这样,项目要实现[System.ComponentModel.Composition.IPartImportsSatisfiedNotification] 接口。这个接口只有一个单独的方法:OnImportsSatisfied,当所有导入可以被满足和已经满足时,它会被调用。
public class Program : IPartImportsSatisfiedNotification { [ImportMany] public IEnumerable<IMessageSender> Senders {get; set;} public void OnImportsSatisfied() { // when this is called, all imports that could be satisfied have been satisfied. } }