我是否可以使用或“投射”一个类的类型(例如,类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
我认为这与问题无关,但是由于它干扰了建议的解决方案/重复项,所以我很吃惊。我还能以某种方式调用该方法吗?
答案 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 });
这是在做什么:
Extensions
方法的AddExceptionTranslation
类中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代码以加快反射速度,但是,我也不必担心。
您可以做的是将上述代码打包成自己的方法,然后对集合中的每种类型进行调用。