在.NET Core中注入通用接口

mic*_*cer 4 c# dependency-injection asp.net-core

我想将此接口注入我的控制器:

public interface IDatabaseService<T>
    where T : class
{
    T GetItem(int id);

    IEnumerable<T> GetList();

    void Edit(T data);

    void Add(T data);

    void Remove(T data);
}
Run Code Online (Sandbox Code Playgroud)

我想用通用的,因为在我WebApi的项目,我有这样的控制器ProjectControllerTaskController等等,我想使用通用接口,每种类型的(例如IDatabaseService<Project>IdatabaseService<Task>等)。

将注入控制器的类如下所示:

public class ProjectService : IDatabaseService<Project>
{
    public ProjectService(DbContext context)
    {
        this.context = context;
    }

    private readonly DbContext context;

    public Project GetItem(int id)
    {
    }

    public IEnumerable<Project> GetList()
    {
    }

    public void Edit(Project data)
    {
    }

    public void Add(Project data)
    {
    }

    public void Remove(Project data)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试注入我的内容时Startup.cs

services.AddScoped<IDatabaseService<T>>();
Run Code Online (Sandbox Code Playgroud)

我需要通过T类型。

我的问题是,如何使注入通用,以及如何在控制器中正确注入?例如:

public class ProjectController : ControllerBase
{
    private readonly ProjectService projectService;

    public ProjectController (IDatabaseService<Project> projectService)
    {
        this.projectService = projectService;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果可以的话?将通用接口注入控制器是否是一种好习惯?如果没有,如何做得更好?

Ton*_*Ngo 13

您可以使用 services.AddScoped 在范围请求中仅使用 1 个实例。因此,与 AddTransient 相比,总体上有所改进

services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
Run Code Online (Sandbox Code Playgroud)

所以我的界面和类看起来像这样

public interface IGenericRepository<T> where T : class
Run Code Online (Sandbox Code Playgroud)
public class GenericRepository<T> : IGenericRepository<T> where T : class
Run Code Online (Sandbox Code Playgroud)


lev*_*ent 12

1.) 如果你想写硬代码

services.AddScoped<IDatabaseService<Project>, ProjectService>();
Run Code Online (Sandbox Code Playgroud)

2.) 如果你想动态注册所有类型的实现 IDatabaseService<>

        System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(item => item.GetInterfaces()
            .Where(i => i.IsGenericType).Any(i => i.GetGenericTypeDefinition() == typeof(IDatabaseService<>)) && !item.IsAbstract && !item.IsInterface)
            .ToList()
            .ForEach(assignedTypes =>
            {
                var serviceType = assignedTypes.GetInterfaces().First(i => i.GetGenericTypeDefinition() == typeof(IDatabaseService<>));
                services.AddScoped(serviceType, assignedTypes);
            });
Run Code Online (Sandbox Code Playgroud)


Voo*_*doo 6

您可以通过在 Startup.cs

// best practice  
services.AddTransient(typeof(IDatabaseService<>),typeof(DatabaseService<>));
Run Code Online (Sandbox Code Playgroud)

访问此处以了解有关ASP.NET Core中的依赖注入的更多信息