Привет! Я использую один общий интерфейс между двумя сервисами. Первоначально интерфейс был общим для двух сервисов 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. Спасибо