Допустим, у меня есть интерфейс службы, который выглядит следующим образом:
public interface IFooService
{
FooResponse Foo(FooRequest request);
}
Я хотел бы выполнить некоторые сквозные задачи при вызове методов для таких служб, как эти; например, я хочу унифицированное ведение журнала запросов, ведение журнала производительности и обработку ошибок. Мой подход состоит в том, чтобы иметь общий базовый класс «Репозиторий» с методом Invoke
, который заботится о вызове метода и выполнении других действий вокруг него. Мой базовый класс выглядит примерно так:
public class RepositoryBase<TService>
{
private Func<TService> serviceFactory;
public RepositoryBase(Func<TService> serviceFactory)
{
this.serviceFactory = serviceFactory;
}
public TResponse Invoke<TRequest, TResponse>(
Func<TService, Func<TRequest, TResponse>> methodExpr,
TRequest request)
{
// Do cross-cutting code
var service = this.serviceFactory();
var method = methodExpr(service);
return method(request);
}
}
Это отлично работает. .Однако всей моей цели сделать код чище мешает тот факт, что вывод типов не работает должным образом.Например, если я пишу такой метод:
public class FooRepository : BaseRepository<IFooService>
{
// ...
public BarResponse CallFoo(...)
{
FooRequest request = ...;
var response = this.Invoke(svc => svc.Foo, request);
return response;
}
}
я получаю эту ошибку компиляции:
Аргументы типа для метода ... не могут быть выведены из использования. Попробуйте указать аргументы типа явно.
Очевидно, я могу исправить это, изменив свой вызов на:
var response = this.Invoke<FooRequest, FooResponse>(svc => svc.Foo, request);
Но я хотел бы избежать этого. способ переработать код, чтобы я мог воспользоваться преимуществами вывода типов?
Редактировать:
Я также должен упомянуть, что более ранний подход заключался в использовании метода расширения; вывод типов для этого работал:
public static class ServiceExtensions
{
public static TResponse Invoke<TRequest, TResponse>(
this IService service,
Func<TRequest, TResponse> method,
TRequest request)
{
// Do other stuff
return method(request);
}
}
public class Foo
{
public void SomeMethod()
{
IService svc = ...;
FooRequest request = ...;
svc.Invoke(svc.Foo, request);
}
}