2015-02-23 30 views
0

我目前正在努力了解如何在控制器类外使用依赖注入模式。依赖注入与多层应用程序

例如说,我有以下控制器:

public class TestController : Controller { 

    ILog logger; 

    public TestController(ILog log) { 

    logger = log; 

    } 

    public string TestMethod() { 

    businessLayer businessLayer = new businessLayer(); 

    return businessLayer.DoSomethingAndLogIt(); 

    } 

} 

据我所知,在大多数情况下是不能使用构造函数注入控制器类之外。因此不可能直接使用ILOG实现,即insdie“businesslayer”类。

一个简单的解决方案,我可以想像如下:

public class TestController : Controller { 

    ILog logger; 

    public TestController(ILog log) { 

    logger = log; 

    } 

    public string TestMethod() { 

    businessLayer businessLayer = new businessLayer(logger); 

    return businessLayer.DoSomethingAndLogIt(); 

    } 

} 

所以传递的依赖从控制器到下伏层。但这是最好的方式吗?是否有更好的解决方案让我的businessLayer级访问ILog实现?

Thx!

回答

3

据我所知,在大多数情况下,不可能使用构造函数 注入控制器类之外。

这是不正确的。您应该为所有组件(包含行为的应用程序中的每个类)使用构造器注入。

依赖注入是关于将相关服务/组件注入消耗组件。所以这意味着你不应该在控制器中新增businesslayer类;你应该使用构造函数注入它。通过创建此依赖关系,您违反了Dependency Inversion Principle,这会导致高耦合。这又使得你的代码更难以测试,并且使得更难控制器更加难以应用横切问题(如日志记录,审计追踪,事务管理等)到系统中。

因此,不可能直接使用ILog实现 插入“businesslayer”类。

错误。应该将ILog实现注入到businesslayer类的构造函数中。

长话短说,你的控制器看起来应该是这样:

public class TestController : Controller { 
    IBusinessLayer businessLayer; 

    public TestController(IBusinessLayer bl) { 
    this.businessLayer = bl; 
    } 

    public string TestMethod() { 
    return businessLayer.DoSomethingAndLogIt(); 

}}

由于TestController似乎并没有直接使用ILog,它不应该被注入到它的构造。 ILog是业务层类的实现细节,实现细节不应泄露给消费者(这又违反了依赖性倒置原则)。

+0

Thx!有一件事我不明白的是IBusinessLayer如何使用ILog实现。但是大多数DI容器似乎能够在注册时解决这个问题。 http://simpleinjector.readthedocs.org/en/latest/using.html#automatic-constructor-injection-auto-wiring – mhtsbt 2015-02-24 07:12:20

+0

@Matthias:这不是关于DI容器。每个类只需接受它(直接)需要的依赖关系作为构造函数参数,并在应用程序的启动路径中构建完整的对象图([Composition Root](http://blog.ploeh.dk/) 2011/07/28/CompositionRoot /))。你不需要一个DI容器来做到这一点,它甚至可以有利于不使用容器。另一方面,DI容器可以帮助使您的Composition Root更加可维护。 – Steven 2015-02-24 08:05:26