djs*_*ner 12 c# decorator func
对于相当模糊的标题表示道歉,但我想要实现的目标可能在代码中有更好的说明.
我有一个WCF客户端.当我调用方法时,我想将每个调用包装在一些错误处理代码中.因此,我没有直接公开方法,而是在客户端类上创建了以下辅助函数:
public T HandleServiceCall<T>(Func<IApplicationService, T> serviceMethod)
{
try
{
return serviceMethod(decorator);
}
[...]
}
Run Code Online (Sandbox Code Playgroud)
客户端代码使用它如下:
service.HandleServiceCall(channel => channel.Ping("Hello"));
Run Code Online (Sandbox Code Playgroud)
对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")
}
}
}
Run Code Online (Sandbox Code Playgroud)
而装饰者本身:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
它真的很笨重而且代码很多.有更优雅的方式吗?
您可以使用表达式,然后检查主体。
就像是
public T HandleServiceCall<T>(Expression<Func<IApplicationService, T>> serviceMethod)
{
try
{
var func = serviceMethod.Compile();
string body = serviceMethod.Body.ToString();
return func(new ConcreteAppService());
}
catch(Exception ex)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)