如何将类型T的typeT强制转换为类T本身以执行Method <t>,其中Method接受lambda参数?

时间:2019-03-25 17:22:29

标签: c# asp.net .net class asp.net-web-api

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

CustomClass

仅知道Method<CustomClass>(); 怎么能实现?

详细问题:

我正在ASP.NET 4.5中开发Web API。对于Startup的IAppBuilder应用,我可以使用一种无​​法更改的扩展方法:

typeof(CustomClass)

此扩展方法用于将扩展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以及其适当的状态代码,唯一ID和我只想在一个地方维护的其他属性。

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

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

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

修改

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

Type

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

1 个答案:

答案 0 :(得分:0)

您需要做的是为集合中的每种类型创建通用方法。这是针对一种类型的方法。下面的代码是人为设计的,但是显示了如何处理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 });

这是在做什么:

这可以解决您的问题,除了一个问题。对于在调用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代码以加快反射速度,但是,我也不必担心。

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