C#:包装方法调用的优雅方式

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)

它真的很笨重而且代码很多.有更优雅的方式吗?

Ric*_*end 2

您可以使用表达式,然后检查主体。

就像是

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)