依赖注入 - 何时使用属性注入

cb_*_*dev 6 c# dependency-injection ioc-container

我有一个类有这样的构造函数:

    private string _someString;
    private ObjectA _objectA;
    private ObjectB _objectB;
    private Dictionary<Enum, long?> _dictionaryA;
    private Dictionary<Tuple<Enum,long?>, long?> _dictionaryB; 

    public SomeDiClass(string someString)
    {
        _someString = someString;

        _objectA = new ObjectA();
        _objectB = new ObjectB();

        _dictionaryA = new Dictionary<Enum, long?>();
        _dictionaryB = new Dictionary<Tuple<Enum, long?>, long?>();
    }
Run Code Online (Sandbox Code Playgroud)

我想从这个构造函数中获取依赖项创建.在第一步中,我将ObjectA和B依赖项移动到构造函数参数,以通过构造函数注入注入它们.我想为此目的使用IoC容器,这就是我现在停留的地方.问题是如何使用someString和词典.我需要将它们注入到类中,因为字典的内容将是单元测试的重要部分.通过属性注入注入字符串和字典是不是一个好主意(我不需要在其他类中使用它们),所以我最终会得到这样的东西?:

    private ObjectA _objectA;
    private ObjectB _objectB;

    public string SomeString { get; set; }
    public Dictionary<Enum, long?> DictionaryA { get; set; }
    public Dictionary<Tuple<Enum, long?>, long?> DictionaryB { get; set; }

    public SomeDiClass(ObjectA objectA, ObjectB objectB)
    {
        _objectA = objectA;
        _objectB = objectB;
    }
Run Code Online (Sandbox Code Playgroud)

有没有最好的做法来解决这样的事情?

Ste*_*ven 18

依赖注入不是一个目标,而是一组特定问题的解决方案.例如,依赖注入可以轻松替换单元测试的抽象,并使您的应用程序更加灵活,因为您可以在不知道消费类的情况下交换,修饰和拦截依赖项.

这并不意味着您应该注入一个类具有的每个依赖项,因为它必须帮助您使类更易于测试并且系统更易于维护.因此,您必须问自己,从测试的角度来看,从外部注入这些词典是否有帮助,或者它是否有助于使您的应用程序更加灵活.

最后一个问题对我来说很难回答,因为你的问题没有足够的细节.但这里有一些指示:

您通常希望注入类的唯一内容是服务和配置值.

服务是一些提供"服务"的合同/抽象/接口.这通常意味着服务将代表您执行某些操作,例如计算价格,与数据库通信,缓存值,返回系统时间,格式化硬盘:)

配置值就是这样; 只是一个价值.但是你需要注入它,因为它不能硬编码到类中,并且你不希望类从ConfigurationManagerfor实例中获取值本身,因为这会创建一个隐藏的依赖(在Configurationmanager)上会使课程更难测试.

其他的东西,比如原语,消息,DTO,集合类型和实体,以及任何其他不提供任何服务(业务逻辑)且不受单元测试影响的东西,都不需要抽象,因此不必注射.在你的情况下,词典是SomeDiClass类的内部状态的一部分,而不是你的类所依赖的服务.

另一方面,如果这些词典被其他服务重用,则必须注入这些词典.但你永远不想直接注入这样的字典本身,因为字典本身不是服务.相反,你需要围绕它们创建一个抽象; 隐藏该字典细节并为应用程序提供服务的东西.

  • +1 TL; DR,但在阅读之后`依赖注入不是一个目标,而是一组特定问题的解决方案'我猜其余的将详细阐述;) (2认同)

Vin*_*Y S 5

当类型的对象创建超出您的控制时,您应该使用属性注入(或设置器注入)。像 aspx Page、HttpHandler、ApiController 等。对于所有其他情况,建议使用构造函数注入。

要使用 StructureMap 解决 aspx 页面的依赖关系,我使用以下方法。

首先,我创建一个 BasePage 类,并在构造函数中使用 StructureMap 的 BuildUp() 方法来解决派生页面的依赖关系。代码如下:

public class BasePage : Page
{
    public BasePage()
    {
        // instruct StructureMap to resolve dependencies
        ObjectFactory.BuildUp(this);
    }
}

public class Default : BasePage
{
     public ICustomerService customerService { get; set; }

     protected void Page_Load(object sender, EventArgs e)
     {
         // can start using customerService
     }
}

public class Login : BasePage
{
     public IAuthenticationService authenticationService { get; set; }

     protected void Page_Load(object sender, EventArgs e)
     {
         // can start using authenticationService
     }
}
Run Code Online (Sandbox Code Playgroud)