在 .NET 7.0 API 控制器项目中使用依赖注入,继承并显式调用基类

问题描述 投票:0回答:1

这是一个学习项目。当派生类在其构造函数中调用基类(参数)时,如何将

IHttpContextAccessor
或任何类注入基服务类而不将其注入派生类?

我试图避免在其构造函数中添加对所有派生类的依赖项,因为它们不会使用它。我有一个基础服务等级:

type namespace MagicVilla_Web.Services
{
    public class BaseService : IBaseService
    {
        public IHttpClientFactory httpClient { get; set; }
        public APIResponse responseModel { get; set; }

       ** public IHttpContextAccessor httpContextAccessor;** //  <== I want to inject this in this class

        public BaseService(IHttpClientFactory httpClient)
        {
            this.responseModel = new();
            this.httpClient = httpClient;         
        }

        public async Task<T> SendAsync<T>(APIRequest apiRequest)
        {
           // do a bunch of stuff
        }
}

以及从 BaseService 类继承但在其构造函数中显式调用 BaseService 的派生类。 SendAsync 函数的常见业务逻辑位于 BaseService 类中,这就是为什么我希望将 IHttpContextAccessor 注入到 BaseService 类中。

每当我注入并调用这些派生服务类时,它们都会使用 1 个参数调用 baseService 构造函数,而我似乎找不到一种方法来使依赖项注入发挥作用

namespace MagicVilla_Web.Services
{
    public class AuthService : BaseService, IAuthService
    {
        private readonly IHttpClientFactory _clientFactory;
        private string villaUrl;

        public AuthService(IHttpClientFactory clientFactory, IConfiguration configuration)  : base(clientFactory)
        {
            _clientFactory = clientFactory;
            villaUrl = configuration.GetValue<string>("ServiceUrls:VillaAPI");
        }

        public Task<T> RegisterAsync<T>(RegistrationRequestDTO obj)
        {
            return SendAsync<T>(new APIRequest()
            {
             //call base class SendAsync with arguments
            });
        }

另一个继承自BaseService的服务类

namespace MagicVilla_Web.Services
{
    public class VillaService : BaseService, IVillaService 
    {

        private readonly IHttpClientFactory _clientFactory;
        private string villaUrl;

        public VillaService(IHttpClientFactory clientFactory, IConfiguration configuration) : base(clientFactory)
        {
            _clientFactory = clientFactory;
            villaUrl = configuration.GetValue<string>("ServiceUrls:VillaAPI");
            
        }

        public Task<T> CreateAsync<T>(VillaCreateDTO dto)
        {
            return SendAsync<T>(new APIRequest()
            {
     //call base class SendAsync with arguments
            });

        }

我尝试向基类添加多个构造函数,但这不起作用,因为基类永远不会直接调用,它的方法仅通过派生类调用,因此 2 个参数构造函数不起作用。

type namespace MagicVilla_Web.Services
{
    public class BaseService : IBaseService
    {

        public IHttpClientFactory httpClient { get; set; }
        public APIResponse responseModel { get; set; }
        public IHttpContextAccessor httpContextAccessor;

public BaseService(IHttpClientFactory httpClient,IHttpContextAccessor httpContextAccessor ) // <== does not work
        {
            this.responseModel = new();
            this.httpClient = httpClient;  
            this.httpContextAccessor = httpContextAccessor;
        }

        public BaseService(IHttpClientFactory httpClient)
        {
            this.responseModel = new();
            this.httpClient = httpClient;         
        }


}

如果我将注入的类添加到所有派生构造函数及其对基类的调用中,那么注入确实可以工作,但这似乎很难维护。

AuthService(IHttpClientFactory clientFactory, IConfiguration configuration, IHttpContextAccessor httpContextAccessor)  : base(clientFactory, httpContextAccessor)

VillaService(IHttpClientFactory clientFactory, IConfiguration configuration, IHttpContextAccessor httpContextAccessor) : base(clientFactory, httpContextAccessor)

我的 Program.cs 中的所有内容都应该正确设置。我没有在任何地方注入 BaseService 类。

            builder.Services.AddScoped<IVillaService, VillaService>();
            builder.Services.AddScoped<IVillaNumberService, VillaNumberService>();
            builder.Services.AddScoped<IAuthService, AuthService>();
         
            builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();```


Is there some way to inject the IHttpContextAccessor into the BaseService class without having to alter the constructors of the derived classes?

I looked at the documentation and didn't see anything that particularly referenced this use case.  https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-usage
c# .net asp.net-mvc inheritance dependency-injection
1个回答
0
投票

如果我将注入的类添加到所有派生构造函数及其对基类的调用中,那么注入确实可以工作,但这似乎很难维护。

确实,这就是继承在 C# 中的工作原理(以及我所熟悉的所有其他语言,可以将其进行比较)。如果基类依赖于某些东西,那么当另一个类继承它时,该依赖关系不会消失。

因此,要么通过链接来提供依赖项,如OP所示,

或者将特定实例硬编码到派生类中(通常不推荐)。

维护起来困难吗?

是的,是的。

解决办法是什么?

优先考虑对象组合而不是类继承。

-

设计模式

不要使用继承作为代码重用的工具。相反,仅在您需要时

注入您需要的服务。

如果上面的内容还不够清楚:

根本不要使用继承。丢弃 BaseService

 类,并提供实现类似 
SendAsync
 等行为的服务。需要该行为的类可以将该服务注入到其构造函数中,而那些不只是忽略它的类。

我从 2002 年左右就开始使用 C# 进行编程,并且已经有十多年没有使用继承了。没有它你也可以轻松做到。这样事情会变得更容易。

© www.soinside.com 2019 - 2024. All rights reserved.