C#中具有未知异常类型的泛型类

时间:2018-08-13 13:46:38

标签: c# json generics exception exception-handling

在我的应用程序Web API中,我有一个异常过滤器,它想捕获任何异常并将其传输到响应包装器类中的客户端。 我的目标是使该异常以正确的类型传输,以便客户端可以重构并重新抛出该异常。

以下是异常捕获器的代码:

public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {

        HttpStatusCode OutputHttpCode = HttpStatusCode.InternalServerError;
        var exceptionType = actionExecutedContext.Exception.GetType();

        if (exceptionType == typeof(InvalidIDException))
        {
            OutputHttpCode = HttpStatusCode.Unauthorized;
        }

        //this way of getting type didnt work for me either
        //var exceptionType = typeof(RestErrorResponse<>).MakeGenericType(actionExecutedContext.Exception.GetType());

        actionExecutedContext.Response = new HttpResponseMessage()
        {
            Content = new StringContent(JsonConvert.SerializeObject(
                //this will not compile here, saying t is a variable but used like a type.
                //If i use generic "Exception" instead everything is working fine,
                //but it will be interpreted as generic exception on client side and
                //could not be handled properly if i rethrow it directly
                new RestErrorResponse<exceptionType> () //Exception will compile
                {
                    Content = null,
                    Status = RestStatus.Error,
                    Exception = actionExecutedContext.Exception
                }
                ),
                    System.Text.Encoding.UTF8, "application/json"),

            StatusCode = OutputHttpCode
        };

        base.OnException(actionExecutedContext);
    }

这是一个具有泛型的类,我正在尝试将异常放入:

public class RestErrorResponse<E> :RestResponse<Object> {
    public E myException { get; set; }
}

如果我在“ RestErrorResponse”类中使用泛型异常,则这是创建的JSON:

{
  "Exception": {
    "ClassName": "InvalidLoginException",
    "Message": "Invalid User Name",
    "Data": {},
    "InnerException": null,
    "HelpURL": null,
    "StackTraceString": "....",
    "RemoteStackTraceString": null,
    "RemoteStackIndex": 0,
    "ExceptionMethod": "....",
    "HResult": -2147024809,
    "Source": "DB",
    "WatsonBuckets": null,
    "ParamName": null
  },
  "Status": {
    "Verbal": "Error",
    "Code": 1074
  },
  "Content": null
}

我的目标是获得:

{
  "InvalidLoginException": {
    "ClassName": "InvalidLoginException",
    "Message": "Invalid User Name",
    "Data": {},
    "InnerException": null,
    "HelpURL": null,
    "StackTraceString": "....",
    "RemoteStackTraceString": null,
    "RemoteStackIndex": 0,
    "ExceptionMethod": "....",
    "HResult": -2147024809,
    "Source": "DB",
    "WatsonBuckets": null,
    "ParamName": null
  },
  "Status": {
    "Verbal": "Error",
    "Code": 1074
  },
  "Content": null
}

1 个答案:

答案 0 :(得分:1)

RestErrorResponse是否在您控制下的类?如果是这样,它真的必须是通用的吗?考虑一下:

tasks:
  - command: sed -i "{{ expression }}" /home/ubuntu/mysql.sql
    vars:
      expression: "{{ (backup_from == 'TEST') | ternary('s/test.abc.com/{{SITE_URL}}/g', 's/abc.com/"{{SITE_URL}}"/g') }}"

现在您可以简单地实例化它:

public class RestErrorResponse : RestResponse<Object> {
    public object Exception { get; set; }
}

如果无法更改,则需要进行反射以创建RestErrorResponse实例。例如:

var response = new RestErrorResponse 
{
     // other properties
     Exception = actionExecutedContext.Exception
}