Извинения за довольно неоднозначный заголовок, но то, что я пытаюсь достичь, вероятно, лучше указано в коде.
У меня есть WCF-клиент. Когда я вызываю методы, я хотел бы объединить каждый вызов в некоторый код обработки ошибок. Таким образом, вместо непосредственного использования методов я создал следующую вспомогательную функцию в классе клиента:
public T HandleServiceCall<T>(Func<IApplicationService, T> serviceMethod)
{
try
{
return serviceMethod(decorator);
}
[...]
}
И клиентский код использует его следующим образом:
service.HandleServiceCall(channel => channel.Ping("Hello"));
И вызов Ping красиво завернут в какую-то логику, которая попытается обработать любые ошибки.
Это отлично работает, за исключением того, что у меня теперь есть требование узнать, какие методы на самом деле вызываются в службе. Первоначально я надеялся просто осмотреть Func<IApplicationService, T>
, используя деревья выражений, но не очень далеко.
Наконец, я остановился на шаблоне Decorator:
public T HandleServiceCall<T>(Func<IApplicationService, T> serviceMethod)
{
var decorator = new ServiceCallDecorator(client.ServiceChannel);
try
{
return serviceMethod(decorator);
}
[...]
finally
{
if (decorator.PingWasCalled)
{
Console.Writeline("I know that Ping was called")
}
}
}
И сам Decorator:
private class ServiceCallDecorator : IApplicationService
{
private readonly IApplicationService service;
public ServiceCallDecorator(IApplicationService service)
{
this.service = service;
this.PingWasCalled = new Nullable<bool>();
}
public bool? PingWasCalled
{
get;
private set;
}
public ServiceResponse<bool> Ping(string message)
{
PingWasCalled = true;
return service.Ping(message);
}
}
Это действительно неуклюжий и довольно много кода. Есть ли более элегантный способ сделать это?