ASP.NET Core 依赖注入单个聚合类而不是多个单独的构造函数注入

Posted

技术标签:

【中文标题】ASP.NET Core 依赖注入单个聚合类而不是多个单独的构造函数注入【英文标题】:ASP.NET Core Dependency Injection Single aggregate class instead of multiple separate constructor injections 【发布时间】:2021-09-20 11:07:15 【问题描述】:

在我的 ASP.NET Core Web API 中,我有几个控制器在其构造函数中接受超过 4-5 个参数,这对我来说看起来不太好。我正在考虑创建一个聚合类,其中包含我经常使用的所有单独对象。 我的意思是,例如,而不是这个:

public SomeController : Controller

    public SomeController(
        IService1 service1,
        IService2 service2,
        Config1 config1,
        Config2 config2)
    
    

这样写:

// of course registered in DI services.AddSingleton<MyToolkit>()
public class MyToolkit 

    public MyToolkit(
        IService1 service1,
        IService2 service2,
        Config1 config1,
        Config2 config2)
    
        ...
    

    public IService1 Service1  get; 
    public IService2 Service2  get; 
    public Config1 Config1  get; 
    public Config2 Config2  get; 


public SomeController : Controller

    private readonly MyToolkit _toolkit;
    public SomeController(MyToolkit toolkit)  _toolkit = toolkit; 

    [HttpGet]
    public IActionResult GetSomething()
    
        return _toolkit.Service1.GetSomething();
    

这种方法(MyToolkit 类)是否违反任何现代设计原则?这种方法是否被视为反模式?

【问题讨论】:

本书DIPP&P(我与人合着)包含关于构造函数过度注入代码气味的一整节(section 6.1)。它提供了几种解决方案,例如Facade Services refactoring、composites、domain events 和decorators。 【参考方案1】:

首先检查控制器级别是否真的需要所有这些依赖项。

具有许多依赖项通常表明主题类很可能做太多事情(违反 SRP)。

如果注入聚合的那些依赖项只是作为属性公开,那么控制器和聚合在明确需要什么来执行其功能方面是不诚实的。 (显式依赖原则)

如果在使用这些依赖项的控制器中发生功能并且实际上应该在其自己的类中,则将该功能及其依赖项抽象出来。 (关注点分离 - SoC)

您当前基于所提供示例的方法只是把罐子踢到路上,可以看作是代码味道。

【讨论】:

在我的例子中,实际上每个控制器都依赖于 ILogger、一些性能计数器、反欺诈、物化 appsettings.json 对象和 MediatR。我只是想为什么不创建和聚合代表某种常用单例对象的存储库的类。无论如何,单例都保留在内存中,因此不会浪费任何资源。 @TiberSeptim 听起来很像cross-cutting concerns 如果您使用 MediatR,您确定不能在装饰器中应用所有这些“关注点”或使用 MediatR 的behavior? @Nkosi,好吧,我想我的设计违反了显式依赖原则。 @TiberSeptim 用于一般异常日志记录,您可以使用异常过滤器抽象日志记录,并在过滤器中添加代码以记录 OnException 和其他场景。这样您就不必在每个控制器中都包含 iLogger。它还删除了所有的 try-catch 代码。如果您的控制器也使用记录器进行自定义记录,即:“工作完成等......”我认为控制器可能不适合这样做。我更喜欢控制器更接近代理的映射器和所有类似的抽象。

以上是关于ASP.NET Core 依赖注入单个聚合类而不是多个单独的构造函数注入的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 依赖注入(DI)

ASP.NET Core 依赖注入最佳实践——提示与技巧

如何解决 ASP.NET Core 中的依赖问题

ASP.NET Core学习——6

ASP.NET Core学习——6

我的 ASP.NET Core MVVM Blazor 应用程序的依赖注入无法正常工作