Asp.net MVC基本控制器,带有构造函数注入和MEF

时间:2012-07-13 09:06:51

标签: asp.net-mvc dependency-injection mef constructor-injection

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

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,因此将mocks注入构造函数参数
  4. 问题

    这对我来说都是有用的,但MEF的想法不同。当我编译并运行此代码时,我得到了这个异常:

      

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

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

    工作替代方案不一样

    当我尝试通过在这些私有字段上直接导入替代方法时,一切似乎都可以正常工作。

    public abstract class LogControllerBase : ControllerBase
    {
        [Import]
        private ILogger logger = null;
    
        protected LogControllerBase() { }
    }
    
    public class SomeController : LogControllerBase
    {
        [Import]
        private IService service = null;
    
        public SomeController() { }
    }
    

    所以这可行,但它不一样......我可以在这里添加构造函数用于依赖注入,但是后来我有两组构造函数,当进行单元测试时,可以使用无参数构造函数,这当然是错误的因为不会设置依赖项。不是真实的,也不是嘲笑。

    问题

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

1 个答案:

答案 0 :(得分:0)

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

var container = new CompositionContainer(catalog, true);