C# 需要重构理念

C# 需要重构理念,c#,generics,asp.net-web-api,C#,Generics,Asp.net Web Api,我有几个WebApi控制器,它们使用2个泛型类进行处理。根据请求中发送的数据,调用一个泛型类。此逻辑封装在Try/Catch中,用于处理超时、身份验证失败和系统错误。当我开始研究GET和POST操作时,基本上都是相同的代码。我试着看看如何重构它,这样就不会有重复的代码。除了提供了请求列表外,帖子基本相同。这是对重构的强烈要求,所以我没有5个不同的控制器,每个控制器都有不同的通用工作流。对重构有什么建议吗?我想尝试将异常逻辑封装到每个控制器将使用的公共位置。我不想将其添加到工作流中,因为我不希望工

我有几个WebApi控制器,它们使用2个泛型类进行处理。根据请求中发送的数据,调用一个泛型类。此逻辑封装在Try/Catch中,用于处理超时、身份验证失败和系统错误。当我开始研究GET和POST操作时,基本上都是相同的代码。我试着看看如何重构它,这样就不会有重复的代码。除了提供了请求列表外,帖子基本相同。这是对重构的强烈要求,所以我没有5个不同的控制器,每个控制器都有不同的通用工作流。对重构有什么建议吗?我想尝试将异常逻辑封装到每个控制器将使用的公共位置。我不想将其添加到工作流中,因为我不希望工作流与作为Web请求的调用方法耦合

下面是代码的示例

private IRequestWorkFlow<RequestTypeA, MyResponse> _WorkFlowA;
private IRequestWorkFlow<RequestTypeB, MyResponse> _WorkFlowB;

public HttpResponseMessage Get([FromUri] RequestTypeA aRequest, [FromUri] RequestTypeB bRequest)
{
    try
    {
        if (!aRequest.IsEmpty())
        {
           var requests = new List<RequestTypeA> { aRequest };
           var aResponses = _WorkFlowA.ProcessRequest(requests);
           return Request.CreateResponse(HttpStatusCode.Ok, aResponses);
        }

        var bRequests = new List<RequestTypeA> { bRequest };
        var bResponses = _WorkFlowB.ProcessRequest(bRequests);
        return Request.CreateResponse(HttpStatusCode.Ok, bResponses);
    }
    catch (TimeoutException ex)
    {
        return Request.CreateErrorResponse(HttpStatusCode.RequestTimeout, ex.Message);
    }
    catch (UnauthorizedAccessException ex)
    {
        return Request.CreateErrorResponse(HttpStatusCode.Forbidden, ex.Message);
    }
    catch (Exception)
    {
        return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Unable to process your request.");
    }
}
私有IRequestWorkFlow\u WorkFlowA;
私有IRequestWorkFlow\u WorkFlowB;
公共HttpResponseMessage Get([FromUri]RequestTypeA请求,[FromUri]RequestTypeB请求)
{
尝试
{
如果(!aRequest.IsEmpty())
{
var请求=新列表{aRequest};
var aResponses=\u WorkFlowA.ProcessRequest(请求);
return Request.CreateResponse(HttpStatusCode.Ok,aResponses);
}
var bRequests=新列表{bRequest};
var breresponses=_WorkFlowB.ProcessRequest(bRequests);
返回请求.CreateResponse(HttpStatusCode.Ok,breResponses);
}
捕获(TimeoutException例外)
{
return Request.CreateErrorResponse(HttpStatusCode.RequestTimeout,ex.Message);
}
捕获(未经授权的访问例外)
{
返回请求.CreateErrorResponse(HttpStatusCode.Forbidden,ex.Message);
}
捕获(例外)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError,“无法处理您的请求”);
}
}

您可以像在基类中那样编辑方法:

HttpResponseMessage Try(Func<HttpResponseMessage> method)
{
    try
    {
        return method.Invoke();
    }
    catch (TimeoutException ex)
    {
        return Request.CreateErrorResponse(HttpStatusCode.RequestTimeout, ex.Message);
    }
    catch (UnauthorizedAccessException ex)
    {
        return Request.CreateErrorResponse(HttpStatusCode.Forbidden, ex.Message);
    }
    catch (Exception)
    {
        return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Unable to process your request.");
    }  
}
httpresponsemessagetry(Func方法)
{
尝试
{
返回方法。Invoke();
}
捕获(TimeoutException例外)
{
return Request.CreateErrorResponse(HttpStatusCode.RequestTimeout,ex.Message);
}
捕获(未经授权的访问例外)
{
返回请求.CreateErrorResponse(HttpStatusCode.Forbidden,ex.Message);
}
捕获(例外)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError,“无法处理您的请求”);
}  
}

您可以创建自定义属性。像这样的

[OnException]
public class HomeController { .... }   

public class OnException: ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        if (context.Exception is TimeoutException)
            return Request.CreateErrorResponse(HttpStatusCode.RequestTimeout, ex.Message);
        if (context.Exception is UnauthorizedAccessException )
            return Request.CreateErrorResponse(HttpStatusCode.Forbidden, ex.Message);
        if (context.Exception is Exception)    
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Unable to process your request.");
    }
}

您可以删除try/catch,OneException会处理它。

我想首先您应该将try/catch代码提取到一个接受
Func
的方法中,并将方法体放在那里。@Smiech是的,我希望有一个单独的位置来放置try/catch,这样控制器就不能对同一问题有不同的响应。我会看看是否能提取逻辑并将其放入基类中。最好的方法是采用SRP和依赖注入您需要的内容。“乐高积木”越小,代码重用就越多,加上一个更健壮的框架作为总体结果。不总是这样,但通常是这样。@Code4Life,我正在使用DI注入工作流。我正在进行的项目是WebApi的一个完整重构,可以完全注入并对每个组件进行单元测试。这是我没有看到将异常逻辑重构到单个点的最后一个方面。然后我认为您应该编辑您的问题,以便更具体地了解您想要什么。这看起来很有趣。我以前做过这样的泛型。我将尝试一下。因为在这种情况下,由于异常处理,您与HttpResponseMessage绑定在一起,所以我编辑了我的回答。这非常有效。另一个好处是过滤器是在WebApiConfig中添加的,因此开发人员不需要记住更改为自定义基类。这段代码需要稍加修改才能正常工作。该方法返回void,因此不能返回请求。我将“退货请求…”改为“上下文。请求…”,然后才退货。谢谢。我没有测试代码,但很高兴它成功了,因为它错过了空白。