Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用泛型封装通用方法工作_C#_Generics - Fatal编程技术网

C# 使用泛型封装通用方法工作

C# 使用泛型封装通用方法工作,c#,generics,C#,Generics,我有很多WebService方法,都包含一些样板代码,将实际工作包装在try/catch/finally中,并在catch/finally中执行相同的任务。因此,为了封装所有共享catch/finally内容,我编写了一个简单的泛型 这样做可以消除大量重复代码,但感觉很笨拙,语法也很迟钝。每次我回到这里,我的大脑都会扭曲,试图找出答案(这是一个明显的迹象,表明这不是一个好的设计)。我正在寻找关于这是否是一件疯狂的事情的反馈,以及是否有更好的方法 这是我的模板: public delegate T

我有很多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委托t2restfulservicerequest(T1请求);
静态类RestfulService
{
公共静态T2异常处理程序(RESTfulServiceRequestServiceCall,T1 req)
{
if(req==null)
抛出新的BadRequestException(新的ArgumentNullException(“无效或缺少请求对象”);
尝试
{
返回serviceCall(req);
}
catch(restfule异常)
{
//记录并重新播放
记录器。写入(e);
投掷;
}
捕获(例外e)
{
错误(e);
//包装一致异常以传播回调用方
抛出新的InternalServerException(e);
}
最后
{
Logger.Debug(“完成”);
}
}
}
}

下面是它的用法:

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);
    }
}
公共类初始化:IInitialization
{
//MyMethodThas使用模板
公共ApplianceInitResp CreateAppianceServer(ApplianceInitReq请求)
{
返回RestfulService.ExceptionHandler(委托(ApplianceInitReq x)
{
//做些工作
返回新的ApplianceInitResp();
},req);
}
}

}

我同意这样做感觉有点笨拙,但是,我现在还没有看到“有效”的方法来重新工作,以最大限度地减少重复


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

让它更干净的一件事是定义请求/响应对象实现的接口。然后,您可以放弃泛型,转而使用接口。同样要注意的是,我认为更名更能说明你真正想做什么

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中会更好

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

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

我喜欢这个解决方案,因为它更容易理解。我看到的唯一缺点是要求所有服务操作都使用从接口派生的参数。除非我需要返回本机类型,否则这没什么大不了的。我必须承认,我不明白‘thist1req’是如何工作的。编译器如何使用正确的泛型?
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();
        });
    }
}