模型类(实体)中的依赖注入 [英] Dependency Injection in Model classes (entities)
问题描述
我正在使用Entity Framework Code-First构建ASP.NET Core MVC应用程序. 我选择实现一个简单的存储库模式,为我创建的所有模型类提供基本的CRUD操作. 我选择遵循 http://docs.asp.net 中提供的所有建议,而DI是其中之一.
I am building an ASP.NET Core MVC application with Entity Framework Code-First. I chose to implement a simple repository pattern, providing basic CRUD operations for all the model classes I have created. I chose to follow all the recommendations provided in http://docs.asp.net and DI is one of these.
在.NET 5中,依赖项注入对于我们不直接实例化的任何类(例如:控制器,数据存储库等)都非常有效.
In .NET 5, dependency injection works very well for any class that we do not directly instanciate (e.g.: controllers, data repositories, ...).
我们只需通过构造函数注入它们,然后将映射注册到应用程序的Startup类中:
We simply inject them via the constructor, and register the mappings in the Startup class of the application :
// Some repository class
public class MyRepository : IMyRepository
{
private readonly IMyDependency _myDependency;
public MyRepository(IMyDependency myDependency)
{
_myDependency = myDependency;
}
}
// In startup.cs :
services.AddScoped<IMyDependency, MyDependency>();
services.AddScoped<IMyRepository, MyRepository>();
我的问题是,在某些模型类中,我想注入一些已声明的依赖项.
The problem I have is that in some of my model classes, I would like to inject some of the dependencies I have declared.
但是我认为我不能使用构造函数注入模式,因为通常显式实例化模型类,因此,我需要向自己提供依赖项,而我不能.
But I think that I cannot use the constructor injection pattern, because model classes are often explicitely instanciated, and therefore, I would need to provide myself the dependencies, which I can't.
所以我的问题是:除了构造函数注入之外,还有其他方法可以注入依赖关系吗?例如,我在考虑一种属性模式或类似的东西.
So my question is: is there another way than constructor injection to inject dependencies, and how? I was for example thinking of an attribute pattern or something like that.
推荐答案
我知道我的回答太迟了,可能不完全是您的要求,但是我想分享我的做法.
I know my answer is late and may not exactly what you're asking for, but I wanted to share how I do it.
首先:如果您希望拥有一个静态类来解析依赖项,则这是 ServiceLocator ,它是 Antipattern ,因此请尝试不要尽可能地使用它. 就我而言,我需要它在DomainModel内部调用 MediatR 来实现
First of all: If you want to have a static class that resolves your dependencies this is a ServiceLocator and it's Antipattern so try not to use it as you can. In my case I needed it to call MediatR inside of my DomainModel to implement the DomainEvents logic.
无论如何,我必须找到一种方法来在DomainModel中调用静态类,以从DI获取某些已注册服务的实例.
Anyway, I had to find a way to call a static class in my DomainModel to get an instance of some registered service from DI.
因此,我决定使用HttpContext
访问IServiceProvider
,但是我需要从静态方法访问它,而在我的域模型中没有提及它.
So I've decided to use the HttpContext
to access the IServiceProvider
but I needed to access it from a static method without mention it in my domain model.
让我们这样做:
1-我创建了一个包装IServiceProvider的接口
1- I've created an interface to wrap the IServiceProvider
public interface IServiceProviderProxy
{
T GetService<T>();
IEnumerable<T> GetServices<T>();
object GetService(Type type);
IEnumerable<object> GetServices(Type type);
}
2-然后我创建了一个静态类作为我的ServiceLocator访问点
2- Then I've created a static class to be my ServiceLocator access point
public static class ServiceLocator
{
private static IServiceProviderProxy diProxy;
public static IServiceProviderProxy ServiceProvider => diProxy ?? throw new Exception("You should Initialize the ServiceProvider before using it.");
public static void Initialize(IServiceProviderProxy proxy)
{
diProxy = proxy;
}
}
3-我为IServiceProviderProxy
创建了一个实现,该实现在内部使用IHttpContextAccessor
3- I've created an implementation for the IServiceProviderProxy
which use internally the IHttpContextAccessor
public class HttpContextServiceProviderProxy : IServiceProviderProxy
{
private readonly IHttpContextAccessor contextAccessor;
public HttpContextServiceProviderProxy(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor;
}
public T GetService<T>()
{
return contextAccessor.HttpContext.RequestServices.GetService<T>();
}
public IEnumerable<T> GetServices<T>()
{
return contextAccessor.HttpContext.RequestServices.GetServices<T>();
}
public object GetService(Type type)
{
return contextAccessor.HttpContext.RequestServices.GetService(type);
}
public IEnumerable<object> GetServices(Type type)
{
return contextAccessor.HttpContext.RequestServices.GetServices(type);
}
}
4-我应该这样在DI中注册IServiceProviderProxy
4- I should register the IServiceProviderProxy
in the DI like this
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddSingleton<IServiceProviderProxy, HttpContextServiceProviderProxy>();
.......
}
5-最后一步是在应用程序启动时用IServiceProviderProxy
实例初始化ServiceLocator
5- Final step is to initialize the ServiceLocator
with an instance of IServiceProviderProxy
at the Application startup
public void Configure(IApplicationBuilder app, IHostingEnvironment env,IServiceProvider sp)
{
ServiceLocator.Initialize(sp.GetService<IServiceProviderProxy>());
}
因此,现在您可以在DomainModel类中或与所需位置"中调用ServiceLocator并解决所需的依赖项.
As a result now you can call the ServiceLocator in your DomainModel classes "Or and needed place" and resolve the dependencies that you need.
public class FakeModel
{
public FakeModel(Guid id, string value)
{
Id = id;
Value = value;
}
public Guid Id { get; }
public string Value { get; private set; }
public async Task UpdateAsync(string value)
{
Value = value;
var mediator = ServiceLocator.ServiceProvider.GetService<IMediator>();
await mediator.Send(new FakeModelUpdated(this));
}
}
这篇关于模型类(实体)中的依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!