Inject generic interface in .NET Core

心已入冬 提交于 2021-01-20 16:11:38

问题


I want to inject this interface to my controllers:

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);
}

I want to use generic, because in my WebApi project i have controllers like ProjectController, TaskController etc and i want to use generic interface to each of type (for example, IDatabaseService<Project>, IdatabaseService<Task> etc).

Class, that will be injected to controller will look like this:

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)
    {
    }
}

But when i try to ineject in my Startup.cs:

services.AddScoped<IDatabaseService<T>>();

I need to pass T type.

My question is, how to make injection generic and how inject it properly in controller? For example:

public class ProjectController : ControllerBase
{
    private readonly ProjectService projectService;

    public ProjectController (IDatabaseService<Project> projectService)
    {
        this.projectService = projectService;
    }
}

If it will work? And is it good practice to make generic interface to inject into controllers? If no, how to do it better?


回答1:


1.) if you want to write hard code

services.AddScoped<IDatabaseService<Project>, ProjectService>();

2.) if you want to register dynamically that all types of implemented 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);
            });



回答2:


You can do this by adding the below line in Startup.cs

// best practice  
services.AddTransient(typeof(IDatabaseService<>),typeof(DatabaseService<>));

Visit Here to know more about Dependency injection in ASP.NET Core




回答3:


You can use services.AddScoped to use only 1 instance in the scope request. So in general improvement compare to AddTransient

services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));

So my interface and class will look like this

public interface IGenericRepository<T> where T : class
public class GenericRepository<T> : IGenericRepository<T> where T : class



回答4:


Feel free to use helpers:

by Generic interface

services.AddAllGenericTypes(typeof(IDatabaseService<>), new[] {typeof(ProjectService).GetTypeInfo().Assembly});

With extensions from: https://gist.github.com/GetoXs/5caf0d8cfe6faa8a855c3ccef7c5a541



来源:https://stackoverflow.com/questions/56143613/inject-generic-interface-in-net-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!