构造函数使用autofac注入基类

gav*_*gav 26 constructor code-injection abstract autofac

我有一个抽象的基本控制器,它有一个构造函数,我希望在构建控制器时由autofac填充.

public abstract class BaseController : Controller
{
    protected ILogger { get; private set; }

    protected BaseController()
    {
    }

    protected BaseController(ILogger logger)
    {
        Logger = logger;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我从它派生一个控制器时,这似乎不起作用.

当我从控制器显式地显式调用构造函数时,我只能使它工作.这是正确的方法吗?

public class PublicController : BaseController
{
    public PublicController()
    {
    }

    public PublicController(ILogger logger) : base(logger)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

此外,使用mvc集成程序集,似乎没有办法共享容器供其他类进行自己的解析.我在某处读到这不鼓励,为什么不呢?这只是为了解耦任何单个ioc框架的依赖性吗?构造函数注入是在heirachy中填充依赖的唯一方法.

谢谢

Nic*_*rdt 55

显式调用基类构造函数是在C#中使用构造函数注入执行此操作的唯一方法.看起来你应该从中删除无参数构造函数BaseController,PublicController因为当记录器可用时它们永远不会被实际调用.

将依赖项注入基本控制器的问题是使用ASP.NET MVC和IoC的常见问题.有几种选择/思想流派.

1.)使用聚合服务.为了简化派生类构造函数,创建一个服务,公开或委托基本控制器所需的所有不同服务(例如IBaseControllerDependencies或类似).然后将这一项服务传递给BaseController正如您在ILogger此处所做的那样.

根据您的应用程序和您正在使用的基类数量,有各种优缺点.谷歌针对'Autofac聚合服务'了解更多信息.

2.)使用属性注入.将ILogger基类上的属性设置为public,并使用以下命令配置容器:

builder.RegisterControllers().PropertiesAutowired();
Run Code Online (Sandbox Code Playgroud)

属性注入并不是Autofac中的首选技术.构造函数的作用接受依赖关系,而可写属性通常被视为代码异味,因此Autofac并不真正针对这种情况进行优化.缺点之一是不应经常注入的可写属性是错误的,带来奇怪的后果.

3.)将基本控制器功能重构为各种动作过滤器.Autofac可以将动作过滤器注入MVC​​动作调用管道.因此,过滤器可以采用基类上的依赖关系,并且可以以交叉方式应用相同的关注点.关于这一点,在网络上,更多的信息ExtensibleActionInvoker.InjectActionInvoker()指向你需要的信息.并非所有问题都可能.

4,也是你的第二个问题的答案.)使用服务位置解决基本控制器依赖关系DependencyResolver.Current.

var logger = DependencyResolver.Current.GetService<ILogger>();
Run Code Online (Sandbox Code Playgroud)

不鼓励这样做的原因是它使得生成的应用程序更难理解,因为通过查看一个位置(构造函数)不再可能看到组件所依赖的服务.确定容器中必须配置的内容在可以使用特定组件之前,必须查看组件的整个代码库以查找GetService()调用.单元测试时存在明显的障碍.

希望这有所帮助,我知道的大脑转储:)其他人可以为这些添加更多的想法.