使用MEF构建可扩展应用程序时的注意事项

时间:2010-03-13 15:37:49

标签: wpf architecture dependency-injection mef

我已经开始尝试我的一个项目的依赖注入(特别是MEF),它有许多不同的可扩展性点。我开始觉得我能用MEF做些什么,但我想听听那些对这项技术有更多经验的人。一些具体案例:

  1. 我目前的主要用例是暴露我的扩展程序使用的各种类似单例的服务。 My Framework程序集公开服务接口,我的Engine程序集包含具体实现。这很好用,但我可能不想让所有扩展程序都能访问我的所有服务。 MEF中是否有一种方法可以限制我允许新实例化扩展解析的特定导入?

  2. 此特定应用程序具有我反复实例化的扩展对象。我可以导入多种类型的控制器和机器,它们以不同的组合形式实例化。我找不到用MEF做这个的好方法,所以我正在进行自己的类型发现和实例化。在MEF或其他DI框架中有没有好的方法呢?

  3. 我欢迎您注意任何其他需要注意的事项,或者您发现的令人惊讶的功能已经改变了您的架构方式。

1 个答案:

答案 0 :(得分:1)

  

MEF中有一个好方法吗?   限制我允许的特定进口   一个新实例化的扩展名   解决?

将扩展程序代码加载到单独的容器中,并确保该容器中的受限制部件不可用。让我们简化这些类的情况来构建一个例子:

[Export]
public class MyExtension
{
   [Import]
   public PublicService Service { get; set; }

}

[Export]
public class PublicService
{
}

[Export]
public class InternalService
{
}

[Export]
public class Program
{
   [Import]
   public MyExtension Extension { get; set; }

   [Import]
   public PublicService Service1 { get; set; }

   [Import]
   public InternalService Service2 { get; set; }
}

目标是允许MyExtension导入PublicService,但 InternalService。像Program这样的内部代码应该可以导入任何内容。你可以这样做:

var publicCatalog = new TypeCatalog(typeof(PublicService), typeof(MyExtension));
var publicContainer = new CompositionContainer(publicCatalog);

var internalCatalog = new TypeCatalog(typeof(Program), typeof(InternalService));
var internalContainer = 
    new CompositionContainer(internalCatalog, publicContainer);

var program = internalContainer.GetExport<Program>();

此代码不会抛出合成异常。如果您现在将MyExtension上的导入更改为禁止InternalService,则会根据需要获得合成异常。

此设置的副作用是PublicService也无法导入任何私人服务,就像MyExtension一样。这种做法是有道理的,因为否则不会阻止PublicService通过财产公开私人服务。

我已使用TypeCatalog作为示例,但在实践中,您应该使用类似FilteredCatalog sample的内容。

  

这个特殊的应用程序有   我反复的扩展对象   实例。我可以导入多个   控制器和机器的类型,   它们被实例化为不同的   项目的组合。我不能   找到一个用MEF做到这一点的好方法,   所以我正在做自己的类型发现   实例。有没有好办法   在MEF或其他DI中执行此操作   框架?

您可能只是在PartCreationPolicy属性之后,该属性控制是否共享某个部件(如每个容器仅创建一次)或每次导入多次实例化。您还可以在导入属性中指定RequiredCreationPolicy参数。

如果这不能解决您的问题,请查看MEF源中的PartCreator sample(但请注意,它可能很快会重命名为ExportFactory,它已经出现在MEF的Silverlight版本中)