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()
调用.单元测试时存在明显的障碍.
希望这有所帮助,我知道的大脑转储:)其他人可以为这些添加更多的想法.