. Net Core DI с использованием Fun c с провайдером - PullRequest
0 голосов
/ 18 марта 2020

Привет! Я использую один общий интерфейс между двумя сервисами. Первоначально интерфейс был общим для двух сервисов ServiceA и ServiceB, но по мере его роста я понял, что ServiceB не понадобятся все методы, доступные в интерфейсе, поэтому я хотел следовать ISP.

Раньше (когда я использовал общий интерфейс) было легко внедрить DI и решить, какая конкретная реализация интерфейса будет использоваться во время выполнения на основе некоторого параметра, переданного из API. Ниже приведен пример того, как я делал это раньше на основе ServiceProvider. ServiceA и ServiceB используют общий интерфейс, поэтому в MyRepo мне просто вызвать метод и не беспокоиться о том, кто его реализует.

Statrtup.cs

services.AddSingleton<ServiceA>();
services.AddSingleton<ServiceB>();

services.AddTransient<Func<ServiceProvider, IBaseService>>(serviceProvider => key =>
{
    switch (key)
    {
        case ServiceProvider.A:
            return serviceProvider.GetService<ServiceA>();

        case ServiceProvider.B:
            return serviceProvider.GetService<ServiceB>();

        default:
            throw new KeyNotFoundException();
    }
});

public interface IServiceA : IBaseService
{
    Task<Response> GetShoppingMethodsAsync(
        ShoppingMethodsRequest request,CancellationToken cancellationToken);

    Task<Response> GetTrolleyAsync(
        TrolleyRequest request, CancellationToken cancellationToken);
}

public interface IServiceB : IBaseService
{
    Task<Response> GetShoppingMethodsAsync(
        ShoppingMethodsRequest request,CancellationToken cancellationToken);

    Task<Response> GetTrolleyAsync(
        TrolleyRequest request, CancellationToken cancellationToken);
}


public class MyRepo    {
    private readonly Func<ServiceProvider, IBaseervice> _service;

    public MyRepo(
        IMapper mapper, IPaymentOptionsService paymentOptionsService,
        Func<ServiceProvider, IBaseService> service)
        {
            _service = service;
        }

    public async Task ConsumeService(Provider p)
    {
       var resp = await _service(P).GetShoppingMethodsAsync(myrequest);
    }
}

Проблема с вышеприведенным подходом заключается в том, что если я хочу применить ISP, то в ConsumeService мне нужно знать, какой это тип интерфейса, прежде чем вызывать его метод, и для этого мне нужно проверить и привести как ниже

    public class MyRepo    {
    private readonly Func<ServiceProvider, IBaseervice> _service;

    public MyRepo(
        IMapper mapper, IPaymentOptionsService paymentOptionsService,
        Func<ServiceProvider, IBaseService> service)
        {
            _service = service;
        }

     public async Task ConsumeService(Provider p)
     {
        var getService =  _service(P);
        if(getService is IServiceA serviceA)
        {
            var resp = await serviceA.GetShoppingMethodsAsync(myrequest);
        }
     }
   }

public class ServiceA:IServiceA
{
    public Task<Response> GetShoppingMethodsAsync(
        ShoppingMethodsRequest request,CancellationToken cancellationToken) { }

    public Task<Response> GetTrolleyAsync(
        TrolleyRequest request, CancellationToken cancellationToken){ } 
}

public class ServiceB : IServiceB
{
    public Task<Response> ProcessAsync(
        Request request, CancellationToken cancellationToken) { }
}

Есть ли другой способ решения этой проблемы, ИЛИ я мог бы вернуть забранный сервис напрямую из DI. Спасибо

...