2011-08-26 51 views
21

我有一个抽象基本控制器,它有一个构造函数,我希望在构建控制器时由autofac填充该构造函数。使用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框架的依赖性吗?构造函数只注入的方式来填充依赖性的依赖性。

感谢

回答

48

显式调用基类构造函数是在C#中使用构造函数注入完成此操作的唯一方法。看起来应该从BaseControllerPublicController中删除无参数的构造函数,因为当记录器可用时,实际上它们不应该被调用。

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

1.)使用聚合服务。为了保持派生类的构造器简单,创建一个公开或委托给基础控制器所需的所有不同服务的单个服务(例如IBaseControllerDependencies或类似的)。然后将这个服务传递给BaseController,就像你在这里使用​​一样。

根据您的应用程序和您正在使用的基类的数量,有各种优点/缺点。Google提供'Autofac聚合服务'以查看更多相关信息。

2.)使用属性注入。让你的基类公众​​属性,使用配置容器:

builder.RegisterControllers().PropertiesAutowired(); 

物业注入是不是真的在Autofac一个首选技术。构造函数的作用接受依赖关系,而可写属性经常被视为代码异味,所以Autofac并没有真正优化这种情况。其中一个缺点是,经常注入的可写属性往往是错误的,并且会带来奇怪的后果。

3.)重构基础控制器功能到各种动作过滤器中。 Autofac可以将动作过滤器注入到MVC动作调用管道中。因此,过滤器可以采用基类中的依赖关系,并且可能以交叉方式应用相同的问题。有关此信息的更多信息,请参阅ExtensibleActionInvoker.InjectActionInvoker()指向您需要的信息。并不总是可能的所有问题。

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

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

这是不鼓励的原因是,它使得生成的应用程序更难理解,因为它不再是可以看到什么样的服务组件经寻找在一个地方依赖(构造)。为了确定必须在使用特定组件之前在容器中配置什么,必须查看组件的整个代码库以查找调用的GetService()。单元测试时显而易见的障碍。

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

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/)。祝你好运!

0

Autofac对.NET核心

安装

PM> Install-Package Autofac.Core.NonPublicProperty 

使用

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