构造函数使用autofac注入基类

时间:2011-08-26 01:20:25

标签: constructor autofac code-injection abstract

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

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

    protected BaseController()
    {
    }

    protected BaseController(ILogger logger)
    {
        Logger = logger;
    }
}

当我从中获取控制器时,这似乎不起作用。

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

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

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

    }
}

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

由于

3 个答案:

答案 0 :(得分:54)

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

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

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

根据您的应用程序和您正在使用的基类数量,有各种优缺点。 Google可以通过“Autofac聚合服务”了解更多信息。

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

builder.RegisterControllers().PropertiesAutowired();

属性注入并不是Autofac中的首选技术。构造函数的角色 接受依赖关系,而可写属性通常被视为代码异味,因此Autofac并不真正针对这种情况进行优化。其中一个缺点是不应该经常注入

的可写属性是错误的,结果很奇怪。

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

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

var logger = DependencyResolver.Current.GetService<ILogger>();

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

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

答案 1 :(得分:2)

我没有评论权限要求更多详细信息,但我需要查看您的注册码,以了解您的期望以及容器未达到预期的原因。

关于你的其他问题:类不一定有办法自己解决,但是一个类可以依赖于一个已知类型的自动可解析对象工厂(这通常就足够了)。如果您已注册A,则可以依赖Func<A>。在Autofac中有很多这样的关系类型;见http://code.google.com/p/autofac/wiki/RelationshipTypes

不鼓励“共享容器”,因为它倾向于隐藏类的依赖关系。如果对容器的依赖性被采用,或被引用为全局“IoC”对象,则特定依赖关系的表达性将丢失。

解决层次结构中的依赖关系不应该是一个问题,因为你已经在使用c'tor注入我不知道你的问题是什么。存在辅助问题,例如,如果基类依赖性发生更改,则修改所有子类。幸运的是,Autofac在Aggregate Services(http://code.google.com/p/autofac/wiki/AggregateService)中有答案。

Autofac是一款非常棒的工具。还有一个建议,如果你刚刚开始,请花一些时间来围绕对象生命周期和生命周期范围(尤其是http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/)。祝你好运!

答案 2 :(得分:1)

Autofac for .NET Core

安装

PM> Install-Package Autofac.Core.NonPublicProperty

使用

builder.RegisterType<AppService>()
  .AsImplementedInterfaces()
  .AutoWireNonPublicProperties();