繁体   English   中英

使用泛型来封装常见的方法工作

[英]Using Generics to encapsulate common method work

我有许多WebService方法都包含一些非常的样板代码,用于将实际工作包装在try / catch / finally中,并在catch / finally中执行相同的任务。 因此,作为一种封装所有共享catch / finally内容的方法,我编写了一个简单的泛型。

这有效并且真正消除了一堆重复的代码,但感觉很笨,而且语法非常迟钝。 每次我回到这里,我的大脑都会扭曲,试图找出它(一个明显的标志,这不是一个好的设计)。 我正在寻找关于这是否是一件疯狂事情的​​反馈,以及是否有更好的方法来解决它。

这是我的模板:

public delegate T2 RestfulServiceRequest<T1, T2>(T1 req);

static class RestfulService
{
    public static T2 ExceptionHandler<T1, T2>(RestfulServiceRequest<T1, T2> serviceCall, T1 req)
    {
        if (req == null)
           throw new BadRequestException(new ArgumentNullException("Invalid or missing request object"));

        try
        {
            return serviceCall(req);
        }
        catch (RestfulException e)
        {
            // log it and rethrow
            Logger.Write(e);
            throw;
        }
        catch (Exception e)
        {
            Logger.Error(e);

            // wrap in a consistent exception for propagation back to caller
            throw new InternalServerException(e);
        }
        finally
        {
            Logger.Debug("Complete");
        }
    }
}

}

以下是它的用法:

public class Initialization : IInitialization
{
    // MyMethod thas uses the template
    public ApplianceInitResp CreateApplianceServer(ApplianceInitReq req)
    {
        return RestfulService.ExceptionHandler<ApplianceInitReq, ApplianceInitResp>(delegate(ApplianceInitReq x)
        {
            // do some work
            return new ApplianceInitResp();
        }, req);
    }
}

}

我会改变

public static T2 ExceptionHandler<T1, T2>(RestfulServiceRequest<T1, T2> serviceCall, T1 req)

public static T2 Invoke<T1, T2>( this T1 req, RestfulServiceRequest<T1, T2> serviceCall)

这会将通话更改为

public class Initialization :IInitialization {
    public ApplianceInitResp CreateApplianceServer( ApplianceInitReq req ) {
        return req.Invoke( r => {
            // do some work
            return new ApplianceInitResp();
        });
    }
}

使其更清晰的一件事是定义请求/响应对象实现的接口。 然后你就可以摆脱泛型,转而使用接口。 请注意,我认为名称更改更能描述您真正想要做的事情。

public interface IServiceResponse { ... }
public class ApplianceInitResp : IServiceResponse { ... }
public interface IServiceRequest { ... }
public class ApplianceInitReq : IServiceRequest { ... }

public delegate IServiceResponse RestfulServiceRequest( IServiceRequest req );

static class RestfulService
{
    public static IServiceResponse
        Invoke( RestfulServiceRequest serviceCall, IServiceRequest req)        
    {
        if (req == null)
            throw new BadRequestException( ...inner-exception... );
         try
         {
            return serviceCall(req);
         }
         catch (RestfulException e)
         {
            Logger.Write(e);
            throw;               
         }
         catch (Exception e)
         {
             Logger.Error(e);
             throw new InternalServerException(e);
         }
         finally
         {
             Logger.Debug("Complete");
         }
    }
}

public class Initialization : IInitialization
{
     // MyMethod thas uses the template 
     public ApplianceInitResp CreateApplianceServer(ApplianceInitReq req) 
     {
          return RestfulService.Invoke(
                    delegate(ApplianceInitReq x)
                    {
                        // do some work
                        return new ApplianceInitResp();
                    },
                    req );
     }
}

我建议你寻找提供AOP功能的框架(如Spring.NET,Unity)。 这些将帮助您减少CreateApplianceServer()调用

public ApplianceInitResp CreateApplianceServer(ApplianceInitReq req)
{
    // Do some work
    return new ApplianceInitResp();
}

通过处理入口/出口和异常日志记录与方面。 也许,如果你有一些常见的参数,你也可以将参数验证插入方面。

当然,会有学习曲线税,但是,相信我,结果值得。 您将大大减少方法中的样板代码量。

我同意这感觉有点笨拙,但是,我并没有立即看到重复工作的“完美”方式,以尽量减少重复。

我唯一想到的是,如果你能以某种方式使用接口或稍微分解一下,我不确定我是怎么做的,但是我可以说,对于正在进行的改变我不认为我会离开这个,至少没有真正好的文档。

我觉得你做的很好。 这种编码在脚本语言中很常见 - 但由于它们是动态类型的,所以它不那么冗长。 它在函数式语言中也很常见 - 但它的冗长程度更低,因为它们具有如此好的类型推断! 在C#中,你受到类型推理系统当前局限性的限制,但在版本4中会更好。

另一种方法是使用大量的接口或类来封装您的工作。 在执行此操作时,您在调用时具有较少的类型名称,但整体代码更多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM