4

我有一个基本控制器类,它向它的子类公开一些日志记录功能。此日志记录依赖项是构造函数注入的。为了提供一些简化的代码,这就是它的样子:

public abstract class LogControllerBase : Controller
{
    private readonly ILogger logger = null;

    protected LogControllerBase(ILogger logger)
    {
        this.logger = logger;
    }
}

我的子控制器也有自己的依赖项,因此它们看起来像这样:

public class SomeController : LogControllerBase
{
    private readonly IService service = null;

    [ImportingConstructor]
    public SomeController(ILogger logger, IService service)
        : base(logger)
    {
        this.service = service;
    }
}

我正在使用这些构造函数来轻松地在我的单元测试中进行依赖注入,但在生产中,所有组合都(应该)由 MEF 完成。我正在使用我的自定义控制器工厂类,它使用 MEF 来实例化控制器。

把它们加起来:

  1. 我有一个基本的抽象控制器类,它有自己的依赖项
  2. 我有后代控制器,它们使用导入来获取 MEF 注入的参数(即它们的依赖项以及基类的依赖项)
  3. 单元测试不使用 MEF,因此将模拟注入构造函数参数

问题

这一切对我来说都成立,但 MEF 的想法不同。当我编译并运行这段代码时,我得到了这个异常:

在先决条件导入 'SomeController..ctor (Parameter="logger", ContractName="ILogger")' 设置之前,无法调用 GetExportedValue。

所有用作构造函数参数的接口类型都InheritedExport设置了属性并具有具体的实现,因此它应该按预期工作。

不同的工作替代方案

当我通过直接在这些私有字段上进行导入来尝试另一种方法时,一切似乎都很好。

public abstract class LogControllerBase : ControllerBase
{
    [Import]
    private ILogger logger = null;

    protected LogControllerBase() { }
}

public class SomeController : LogControllerBase
{
    [Import]
    private IService service = null;

    public SomeController() { }
}

所以这可行,但不一样......我可以在这里添加构造函数以进行依赖注入,但是我会有两组构造函数,并且在进行单元测试时可能会使用无参数构造函数,这当然是错误的,因为没有依赖关系会得到设置。不是真实的,也不是模拟的。

问题

如何通过将依赖注入构造函数设置为在构造函数中注入具体实现来说服 MEF 创建我的控制器ImportingConstructor

4

1 回答 1

0

这可能与线程有关,因为默认情况下 MEF 容器不是线程安全的。在容器的构造函数中,尝试启用线程安全:

var container = new CompositionContainer(catalog, true);
于 2012-07-13T10:21:52.480 回答