AddExceptionTranslation

AddExceptionTranslation

我是否可以使用或“投射”类的类型(例如,类CustomClass的类,因此是typeof(CustomClass))来执行一种方法,该方法依赖于提供其相应的类CustomClass作为“参数”?

Method<CustomClass>();


仅知道typeof(CustomClass)如何实现?

详细问题:

我正在ASP.NET 4.5中开发Web API。对于Startup的IAppBuilder应用程序,我可以访问无法更改的扩展方法:

public static class AppExtensions
{
    public static void AddExceptionTranslation<TException>(
        this IAppBuilder app,
        HttpStatusCode statusCode,
        Func<TException, ApiErrors> messageGenerator))
        where TException : Exception;
}


此扩展方法用于将扩展了Exception的自定义异常转换为其相应的状态代码。我正在如下使用它:

public static void SetUpExceptionHandling(IAppBuilder app)
{
    app.AddExceptionTranslation<CustomException>(HttpStatusCode.BadRequest, e => e.ToApiErrors());
    app.AddExceptionTranslation<CustomUnauthException>(HttpStatusCode.Forbidden, e => e.ToApiErrors());
    // ...
}


现在,我必须为每个自定义异常手动添加一个条目,并在每种情况下提供TException。我已经在维护一个数据结构,其中包含每个自定义异常类的typeof以及其相应的状态代码,唯一ID和我只想在一个地方维护的其他属性。

我想使用这个现有的数据结构来遍历它,并对每个自定义异常执行AddExceptionTranslation<TException>,我知道它们的Type

这可能吗?如果不是,我的结构化数据是否可能包含其他内容?当然,我可以咬一口苦瓜,将每个新的自定义异常添加到数据结构中,并手动添加一个用于方法执行的条目,但我真的很想使后者自动化。

请让我知道是否可以澄清。谢谢!

编辑

AddExceptionTranslation实际上接受第二个参数,即lambda表达式,该参数应用于自定义异常:

app.AddExceptionTranslation<CustomException>(HttpStatusCode.Forbidden, e => e.ToApiErrors());

我认为这与该问题无关,但是由于它干扰了建议的解决方案/重复项,因此我感到很酸。我还能以某种方式调用该方法吗?

最佳答案

您需要为集合中的每种类型创建通用方法。这是针对一种类型的方法。下面的代码是人为设计的,但是显示了如何处理lambda。

var exceptionType = typeof(CustomException);

Func<CustomException, ApiErrors> func = e => e.ToApiErrors();

typeof(Extensions)
    .GetMethod(nameof(Extensions.AddException))
    .MakeGenericMethod(exceptionType)
    .Invoke(null, new object[] { builder, HttpStatusCode.Accepted, func });


这是做什么的:


从包含Extensions方法的AddExceptionTranslation类中
我们get that method,这是通用的,然后
指定的异常类型可调用的make a version of that
然后是call that method,因为它是静态的,所以我们为对象类型传递null


除了一个问题,这可以解决您的问题。对于在调用Func之前提取的Invoke的每个异常,您仍然必须“硬编码”异常类型。要解决此问题,请更换

Func<CustomException, ApiErrors> func = e => e.ToApiErrors();




var funcType = typeof(Func<,>).MakeGenericType(exceptionType, typeof(ApiErrors));
var errorsMethod = typeof(ApiErrorsExtension).GetMethod(nameof(ApiErrorsExtension.ToApiErrors));
var func = Delegate.CreateDelegate(funcType, errorsMethod);


哪一个


创建Func<,>的可用版本
获取您真正尝试调用的ToApiErrors()方法,
创建一个可以传递给AddExceptionTranslation方法的委托


因为这使用反射,所以它很慢。因为您是在启动时这样做的,所以没关系。如果可以的话,有一些库可以缓存反射并发出更快的IL代码以加快反射速度,但是同样,我也不必担心。

您可以做的是将上述代码打包成自己的方法,然后对集合中的每种类型进行调用。

10-07 12:24