Dependency injection 减少依赖项数量的好方法是什么?

Dependency injection 减少依赖项数量的好方法是什么?,dependency-injection,Dependency Injection,我使用依赖注入已经有相当一段时间了,我真的很喜欢这项技术,但是我经常遇到一个问题,太多的依赖项应该注入4-5,这似乎太多了 但我找不到一个简单的方法。例如,我有一个带有发送消息的业务逻辑的类,它接受另外两个业务逻辑依赖项来执行所需的操作(一个用于将数据转换为发送的消息,另一个用于转换接收的消息) 但除此之外,它还需要一些“技术”依赖项,如ILogger,ITimerFactory(因为它需要在内部创建计时器),IKeyGenerator(生成唯一密钥) 因此,整个列表变得相当大。有什么好的通用方

我使用依赖注入已经有相当一段时间了,我真的很喜欢这项技术,但是我经常遇到一个问题,太多的依赖项应该注入4-5,这似乎太多了

但我找不到一个简单的方法。例如,我有一个带有发送消息的业务逻辑的类,它接受另外两个业务逻辑依赖项来执行所需的操作(一个用于将数据转换为发送的消息,另一个用于转换接收的消息)

但除此之外,它还需要一些“技术”依赖项,如
ILogger
ITimerFactory
(因为它需要在内部创建计时器),
IKeyGenerator
(生成唯一密钥)


因此,整个列表变得相当大。有什么好的通用方法可以减少依赖项的数量吗?

处理这些依赖项的一种方法是对聚合(或外观)进行重构。马克·希曼(MarkSeemann)写了一篇很好的文章(实际上我也极力推荐,只是说)。 因此,假设您有以下内容(摘自文章):

您可以将其重构为:

public OrderProcessor(IOrderValidator validator,
                      IOrderShipper shipper,
                      IOrderCollector collector)
其中,
OrderCollector
是一个facade(它包装了前面的3个依赖项):

我希望这有帮助

编辑

关于横切关注点(例如日志和缓存)以及处理这些关注点的策略,这里有一个建议(我通常就是这么做的),假设您有以下几点:

public interface IOrderService
{
    void DoAwesome();
}

public class OrderService : IOrderService
{
    public void DoAwesome()
    {
        // do your thing here ... no logging no nothing
    }
}
在这里,我将使用decorator模式创建启用了日志记录的OrderService:

public class OrderServiceWithLogging : IOrderService
{
    private readonly IOrderService _orderService;
    private readonly ILogger _logger;

    public OrderServiceWithLogging(IOrderService orderService, ILogger logger)
    {
        _orderService = orderService;
        _logger = logger;
    }

    public void DoAwesome()
    {
        _orderService.DoAwesome();
        _logger.Log("Awesome is done!");
    }
}
它可能看起来有点开销,但我想,它是干净的,可测试的


另一种方法是进入面向方面的编程,并研究诸如拦截之类的概念,基本上你拦截某些方法调用并执行任务。许多DI框架(我想说全部?)都支持拦截,所以这可能是您更喜欢的东西。

在他的文章中,他确实考虑了一个facade,它利用了一个接一个的东西,因此可以在一个facade中收集。但是我的依赖项不具有相同的逻辑。。。例如,你是如何加入logger and timer factory的?我不会,logger是一个跨领域的公司(IMHO),我会采用不同的策略。那么对这种不同的策略有什么建议吗?@IlyaChernomordik我做了一些编辑,因为评论部分会很长。
public interface IOrderService
{
    void DoAwesome();
}

public class OrderService : IOrderService
{
    public void DoAwesome()
    {
        // do your thing here ... no logging no nothing
    }
}
public class OrderServiceWithLogging : IOrderService
{
    private readonly IOrderService _orderService;
    private readonly ILogger _logger;

    public OrderServiceWithLogging(IOrderService orderService, ILogger logger)
    {
        _orderService = orderService;
        _logger = logger;
    }

    public void DoAwesome()
    {
        _orderService.DoAwesome();
        _logger.Log("Awesome is done!");
    }
}