c# - 在 ASP.NET Core 中的方法中注入依赖项
问题描述
我有以下场景:我在课堂上注册了一个ICompanyDocumentsService
具有单个实现的服务:CompanyDocumentsService
Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ICompanyDocumentService, CompanyDocumentService>();
}
我在很多地方都需要这项服务,而且在构造函数中使用 DI 并不会打扰我。但是,有一个地方我需要在方法中注入它(或者可能在属性中会更好):
public abstract class CompanyDocumentBase
{
public abstract object GetAllProperties(Employee employee, string properties,
CompanyDocumentReferenceData documentReferenceData);
// blah, blah, lots of Formatting Methods
private CompanyDocumentService CompanyDocumentService { get; set; } // **inject service here**
public string GetFormattedEmployeeIndividualEmploymentAgreementNumber(Employee employee,
ICompanyDocumentService companyDocumentService = null) // **optional because
//inherited class doesn't need to know anything about this service, it concerns only it's result**
{
companyDocumentService = CompanyDocumentService;
var test =
companyDocumentService.GetEmloyeeIndividualEmploymentAgreementNumber(employee.Id);
return string.Empty;
}
}
有很多继承的类CompanyDocumentBase
只关心它的方法结果,如上所述,这就是为什么该参数是可选的,这就是为什么我不需要在构造函数中注入 DI,因此继承类将不需要那个。
public class JobDescriptionCompanyDocument : CompanyDocumentBase
{
public override object GetAllProperties(Employee employee,
string properties, CompanyDocumentReferenceData documentReferenceData)
{
var document = JsonConvert.DeserializeObject<JobDescriptionModel>(properties);
document.IndividualEmploymentAgreementNumber = GetEmployeeIndividualEmploymentAgreementNumber(employee);
return document;
}
}
有什么简单的方法可以实现这一目标吗?最好不需要安装像 Unity 或 Autofac 这样的单独库。理想的方法是以某种方式将实例CompanyDocumentsService
直接放入该属性中,例如:
private CompanyDocumentService CompanyDocumentService => Startup.Services.blah that instance
解决方案
一种 hack 方式(我个人不推荐)是在构建容器之后,您可以解析一个实例IHttpContextAccessor
并将其设置为静态类,例如IoC
那你就可以了private CompanyDocumentService CompanyDocumentService => IoC.HttpContextAccessor.HttpContext.RequestServices.GetService()
。
该接口是一个单例,并提供从静态上下文访问作用域服务。
请注意,您可能必须显式注册 HttpContextAccessor: https ://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-3.1
更新
我会推荐什么
如果您对对象工厂持开放态度,并更改了DocumentBase
实例化方式,请尝试创建工厂,并且当您需要 的实例时DocumentBase
,仅使用工厂来创建它:
public abstract class CompanyDocumentBase
{
// Use internal so that access only limited to friendly assembly
internal CompanyDocumentService CompanyDocumentService { get; set; }
}
// Inject this class to where you need to create an instance of CompanyDocumentBase
public class CompanyDocumentFactory<T> where T : CompanyDocumentBase
{
private readonly IServiceProvider _services;
// DI contaiener has implicit IServiceProvider support, when you do this on constructor, it injects service provider of *current* scope
// If this factory is registered as singleton, you need to use IHttpContextAccessor to use request's service provider in Create method
// because your DocumentService is scoped.
public CompanyDocumentFactory(IServiceProvider services)
{
_services = services;
}
public T Create()
{
// Create an instance of document use your current method.
var instance = new T();
instance.CompanyDocumentService = _services.GetRequiredService<ICompanyDocumentService>();
return instance;
}
}
推荐阅读
- unity3d - 如何使用 Unity 中的按钮切换/更改前后 Vuforia AR 摄像头?
- firebase - 可以从 Firestore 快照 Flutter 中获取元数据吗?
- swift - 如何在 MacOS 中正确显示 xib 文件的模态视图?
- microsoft-graph-api - 使用 Microsoft Flow 创建新的 Planner
- python - 密码重置链接重定向到解释域页面
- python - Python 产生:OSError: [WinError 193] %1 不是有效的 Win32 应用程序
- model-fitting - C5.0 只返回一片叶子
- database - PL/SQL - 提高性能的 NOCOPY 参数
- xml - 从 ANT 进行 XSLT 转换以使用结果文档创建多个文档的问题
- java - 在 iTextPdf 中将数字拆分为多个 PdfTextFormField