模型类(实体)中的依赖注入 [英] Dependency Injection in Model classes (entities)

查看:169
本文介绍了模型类(实体)中的依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆