首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >依赖注入-何时使用属性注入

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

Stack Overflow用户
提问于 2013-09-13 14:45:32
回答 2查看 23.1K关注 0票数 11

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

代码语言:javascript
复制
    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?>();
    }

我想从这个构造函数中创建依赖项。在第一步中,我将把ObjectA和B依赖项移动到构造器参数,以便通过构造器注入注入它们。我想使用一个IoC容器来实现这个目的,这就是我目前坚持的地方。问题是如何处理someString和字典。我需要将它们注入到类中,因为字典的内容将是单元测试的重要部分。通过属性注入注入字符串和字典是不是一个好主意(我在其他类中不需要它们),这样我就会得到这样的结果::

代码语言:javascript
复制
    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;
    }

有没有解决这类问题的最佳实践?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-09-13 15:19:18

依赖注入不是最终目标,而是一组特定问题的解决方案。例如,依赖项注入可以轻松地替换单元测试的抽象,并使您的应用程序更加灵活,因为您可以交换、修饰和拦截依赖项,而不必更改消费类。关于依赖注入的一个很好的介绍可以在Dependency Injection Principles, Practices, and Patterns (DIPP&P)这本书的免费chapter 1中找到。

这并不意味着您应该注入类的每个依赖项,因为它必须帮助您使类更具可测试性,使系统更易于维护。因此,您必须问自己,从测试的角度来看,从外部注入这些字典是否有帮助,或者是否有助于使您的应用程序更灵活。为了很好地掌握注入什么和不注入什么,你应该学习挥发和稳定依赖的概念,这些概念可以在DIPP&P的第1章的section 1.3中阅读。

从测试或可维护性的角度来看,它是否有帮助是一个很难回答的问题,因为您的问题没有足够的细节。但这里有一些建议:

您通常唯一想要注入到类中的是服务和配置值。

  • 服务是一些提供“服务”的契约/抽象/接口。这通常意味着服务将代表您执行某些操作,例如计算价格、与数据库通信、缓存值、返回系统时间或格式化您的硬盘驱动器:)
  • 配置值就是它本身;只是一个值。但您需要注入它-它不能被硬编码到类中,例如,您不希望类本身从ConfigurationManager中获取值,因为这将创建一个隐藏的依赖项(在Configurationmanager上),这将使类更难测试。

其他东西,比如原语、消息、DTO、集合类型和实体,以及任何其他不提供任何服务(业务逻辑)且不妨碍单元测试的东西,都不需要抽象,因此也不需要注入(实际上是shouldn't be injected through the constructor or property)。在您的例子中,字典记录了SomeDiClass类的内部状态的一部分,而不是您的类所依赖的服务。

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

票数 26
EN

Stack Overflow用户

发布于 2013-10-07 07:29:07

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

要使用StructureMap解析aspx Page的依赖项,我使用以下方法。

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

代码语言:javascript
复制
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
     }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18779894

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档