为什么模块中没有MEF-container?

时间:2012-05-30 11:02:23

标签: prism mef containers

在我的Prism应用程序中,MEF容器可以通过Container属性从Bootstrapper类中获得。

但它不是来自类模块(IModule)。我只能通过IServiceLocator导入容器。

为什么呢?我认为使用针对具体技术的通用接口是有意义的,但Prism 4.1指南要求我们不要使用IServiceLocator(在Considerations for Using IServiceLocator中)。

2 个答案:

答案 0 :(得分:6)

我认为它不符合Prism或MEF,而是与依赖注入原则和一般的最佳实践相对应。 (是的,我知道MEF不是DI容器,但是这里它几乎用作DI容器,所以我想在这里使用相同的做法。)

在DI的最佳实践中(this本书非常酷,我强烈推荐它)在DI“工作流程”中有这样的步骤是很好的:

  • 注册所有必需的类型(在Prism中 - 通过Bootstrapper.ConfigureCatalog()方法)
  • 解析根对象(包含所有嵌套对象。在Prism中 - 通过Bootstrapper.CreateShell()方法)
  • 使用您的根对象
  • 释放根对象

理想情况下,您不应再使用DI容器。你的代码不应该知道DI容器的存在(从这一方面来看,Unity实际上是DI容器,因为你可以编写不知道使用DI容器的代码)。如果你的代码知道它 - 它在DI容器上存在,这是件坏事。

PS。如果你想在你的模块中使用MEF容器(例如,因为你不熟悉DI范例或者你有一些非常具体的任务),你可以尝试类似的东西:

[ModuleExport(typeof(YourModule))]
public class YourModule : IModule
{
    public static CompositionContainer CompositionContainer;

    [ImportingConstructor]
    public void YourModule(CompositionContainer container)
    {
        this.CompositionContainer = container;
    }
}

不要忘记在Boostrapper中注册您的MEF容器:

public class YourBootstrapper: MefBootstrapper
{
    protected override CompositionContainer CreateContainer()
    {
        var container = base.CreateContainer();
        container.ComposeExportedValue(container);
        return container;
    }
}

答案 1 :(得分:0)

请注意,我使用的是较旧版本的Prism,而我正在使用它与UnityContainer,但同样的原则应该适用。

定义Module类以在构造函数中获取容器。

以下是使用Unity的示例:

public class Module : IModule
{
    public static IUnityContainer Container;

    public Module(IUnityContainer container)
    {
        Container = container;
    }
}

如果你定义一个带容器的构造函数,它将被ApplicationBootstrapper.Run()方法调用。

我使用默认的无参数构造函数和一个重载构造函数进行测试,该构造函数接受容器并调用第二个构造函数。

我还检查过只有默认构造函数并且它被调用了。我建议你改变你的构造函数来添加一个带容器的参数。

在模块类中使用容器将允许您在Initialize方法中注册类型。

对于ServiceLocator,这是一个稍微不同的模式,我建议您在出于某种原因无法获取容器创建的依赖项的情况下使用它。