Извинения за довольно неоднозначное название, но то, что я пытаюсь достичь, возможно, лучше указано в коде.C#: Элегантный способ обертывания вызовов методов
У меня есть клиент 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")
}
}
}
И сам декоратор:
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);
}
}
Это действительно неуклюжим и довольно много кода. Есть ли более элегантный способ сделать это?
Где вы создаете декоратор? – smartcaveman
Выражение деревьев должно быть путем. Можете ли вы показать код и сообщить нам, в чем проблема? –
Звучит как работа для PostSharp. – geofftnz