Извиняюсь за довольно двусмысленный заголовок, но то, что я пытаюсь достичь, вероятно, лучше сформулировано в коде.
У меня есть клиент WCF. Когда я вызываю методы, я хотел бы обернуть каждый вызов в некоторый код обработки ошибок. Итак, вместо непосредственного предоставления методов, я создал следующую вспомогательную функцию для клиентского класса:
public T HandleServiceCall<T>(Func<IApplicationService, T> serviceMethod)
{
try
{
return serviceMethod(decorator);
}
[...]
}
И клиентский код использует его так:
service.HandleServiceCall(channel => channel.Ping("Hello"));
И вызов Пинга красиво оборачивается некоторой логикой, которая попытается обработать любые ошибки.
Это прекрасно работает, за исключением того, что теперь у меня есть требование знать, какие методы в действительности вызываются в службе. Сначала я надеялся просто проверить 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")
}
}
}
И сам Декоратор:
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);
}
}
Это действительно неуклюжий и довольно много кода. Есть ли более элегантный способ сделать это?