6

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

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

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

4

2 回答 2

6

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

在 DI 的最佳实践中(本书很酷,我强烈推荐它)在 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;
    }
}
于 2012-05-31T04:57:58.877 回答
0

请注意,我使用的是旧版本的 Prism,并且我将它与 UnityContainer 一起使用,但同样的原则应该适用。

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

以下是使用 Unity 的示例:

public class Module : IModule
{
    public static IUnityContainer Container;

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

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

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

我还检查了只有默认构造函数,它被调用了。我建议您更改构造函数以添加带有容器的参数。

在模块类中拥有一个容器将允许您在 Initialize 方法中注册类型。

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

于 2012-05-30T20:05:56.220 回答