如何在 ASP.NET Core 中获取没有构造函数注入的注入服务的实例?
How to get an instance of an injected service without constructor injection in ASP.NET Core?
我有一个三层架构。
我无法使用构造函数注入,我需要访问我的业务代码中的服务,而我在其中无法访问 HttpContext
。
例如,在操作方法、过滤器或中间件中,我可以使用以下方式获得服务:
HttpContext.RequestServices.GetRequiredService<ITranslator>();
但是在我的业务代码中,我无权访问HttpContext
。
如何获取我的服务实例?
更新:
这是我的业务代码:
public class InvoiceBusiness
{
// for some reasons, I can't use constructor injection here
public void CalculateTranslationsInvoice(long customerId)
{
// I need to get an instance of ITranslator here, and a couple of other services.
// If this method was in a controller, I could use HttpContext.RequestServices.
// But here what should I do?
}
}
如果您需要访问内层的 HTTP 问题,您应该将其抽象为一个接口。
假设您需要访问当前用户。通常,您会使用 HttpContext.User
。但是在domain层是访问不到的。
解决方案是在您的域层中定义一个接口,该接口封装您的ITranslator
实现实际需要从 HTTP 上下文。
public interface IUserAccessor {
ClaimsPrincipal CurrentUser { get; }
}
public class Translator: ITranslator {
// inject the interface
private readonly IUserAccessor _userAccessor;
public Translator(IUserAccessor userAccessor) {
_userAccessor = userAccessor;
}
// ...
}
让这个界面尽可能集中。在这里,我可以使用 ClaimsPrincipal
并依赖于标准库,但如果你不这样做,如果这在你的应用程序中有意义,你可以只提取用户 ID 声明。
然后在application/HTTP层实现这个接口
internal class HttpUserAccessor: IUserAccessor {
IHttpContextAccessor _httpAccessor;
public HttpUserAccessor(IHttpContextAccessor httpAccessor) {
_httpAccessor = httpAccessor;
}
public ClaimsPrincipal CurrentUser => _httpAccessor.HttpContext?.User;
}
然后注册这个实现:
services.AddHttpContextAccessor();
services.AddScoped<IUserAccessor, HttpUserAccessor>();
现在您可以在任何层访问 HTTP 关注点,而该层不知道数据的实际来源。
底线是:您不必放弃依赖项注入。您可以在不同层定义和实现接口。
我有一个三层架构。
我无法使用构造函数注入,我需要访问我的业务代码中的服务,而我在其中无法访问 HttpContext
。
例如,在操作方法、过滤器或中间件中,我可以使用以下方式获得服务:
HttpContext.RequestServices.GetRequiredService<ITranslator>();
但是在我的业务代码中,我无权访问HttpContext
。
如何获取我的服务实例?
更新:
这是我的业务代码:
public class InvoiceBusiness
{
// for some reasons, I can't use constructor injection here
public void CalculateTranslationsInvoice(long customerId)
{
// I need to get an instance of ITranslator here, and a couple of other services.
// If this method was in a controller, I could use HttpContext.RequestServices.
// But here what should I do?
}
}
如果您需要访问内层的 HTTP 问题,您应该将其抽象为一个接口。
假设您需要访问当前用户。通常,您会使用 HttpContext.User
。但是在domain层是访问不到的。
解决方案是在您的域层中定义一个接口,该接口封装您的ITranslator
实现实际需要从 HTTP 上下文。
public interface IUserAccessor {
ClaimsPrincipal CurrentUser { get; }
}
public class Translator: ITranslator {
// inject the interface
private readonly IUserAccessor _userAccessor;
public Translator(IUserAccessor userAccessor) {
_userAccessor = userAccessor;
}
// ...
}
让这个界面尽可能集中。在这里,我可以使用 ClaimsPrincipal
并依赖于标准库,但如果你不这样做,如果这在你的应用程序中有意义,你可以只提取用户 ID 声明。
然后在application/HTTP层实现这个接口
internal class HttpUserAccessor: IUserAccessor {
IHttpContextAccessor _httpAccessor;
public HttpUserAccessor(IHttpContextAccessor httpAccessor) {
_httpAccessor = httpAccessor;
}
public ClaimsPrincipal CurrentUser => _httpAccessor.HttpContext?.User;
}
然后注册这个实现:
services.AddHttpContextAccessor();
services.AddScoped<IUserAccessor, HttpUserAccessor>();
现在您可以在任何层访问 HTTP 关注点,而该层不知道数据的实际来源。
底线是:您不必放弃依赖项注入。您可以在不同层定义和实现接口。