Внедрить универсальный интерфейс в .NET Core - PullRequest
4 голосов
/ 15 мая 2019

Я хочу внедрить этот интерфейс в мои контроллеры:

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

Я хочу использовать универсальный, потому что в моем проекте WebApi у меня есть контроллеры, такие как ProjectController, TaskController и т. Д., И я хочуиспользовать универсальный интерфейс для каждого типа (например, 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)
    {
    }
}

Но когда я пытаюсь ввести в мой Startup.cs:

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

Iнужно передать T тип.

Мой вопрос: как сделать инъекцию универсальной и как правильно вводить ее в контроллер?Например:

public class ProjectController : ControllerBase
{
    private readonly ProjectService projectService;

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

Если это будет работать?И является ли хорошей практикой создание универсального интерфейса для внедрения в контроллеры?Если нет, как это сделать лучше?

Ответы [ 3 ]

6 голосов
/ 15 мая 2019

Вы можете сделать это, добавив следующую строку в Startup.cs

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

Посетите Здесь , чтобы узнать больше о Внедрение зависимостей в ASP.NET Core

4 голосов
/ 15 мая 2019

1.) Если вы хотите написать жесткий код

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

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);
            });
1 голос
/ 15 мая 2019

Вы можете использовать services.AddScoped для использования только 1 экземпляра в запросе области. Так что в целом улучшение по сравнению с AddTransient

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

Так что мой интерфейс и класс будут выглядеть так

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