这是一个学习项目。当派生类在其构造函数中调用基类(参数)时,如何将
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
每当我注入并调用这些派生服务类时,它们都会使用 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# 中的工作原理(以及我所熟悉的所有其他语言,可以将其进行比较)。如果基类依赖于某些东西,那么当另一个类继承它时,该依赖关系不会消失。
因此,要么通过链接来提供依赖项,如OP所示,或者将特定实例硬编码到派生类中(通常不推荐)。
维护起来困难吗?是的,是的。
解决办法是什么?
优先考虑对象组合而不是类继承。不要使用继承作为代码重用的工具。相反,仅在您需要时-
注入您需要的服务。
如果上面的内容还不够清楚:根本不要使用继承。丢弃 BaseService
类,并提供实现类似
SendAsync
等行为的服务。需要该行为的类可以将该服务注入到其构造函数中,而那些不只是忽略它的类。我从 2002 年左右就开始使用 C# 进行编程,并且已经有十多年没有使用继承了。没有它你也可以轻松做到。这样事情会变得更容易。