可以使用来自反射的类型作为类型参数吗?例:我想根据传递的对象选择一个持久性对象:
IPersister GetPersisterFor(IEntity entity)
{
return GetPersisterFor<entity.GetType()>(); // <-- this cannot be compiled
}
IPersister GetPersisterFor<TEntity>() where TEntity : IEntity
{
//some logic to get persister...
}
只能通过反射;您需要使用GetMethod
来获取通用方法的MethodInfo
,然后在其上调用MakeGenericMethod(entity.GetType()).Invoke(this, null);
。
IPersister Evil<T>(T obj) where T : IEntity {
return GetPersisterFor<T>();
}
让第一个方法变成:
return Evil((dynamic)entity);
这是一个动态表达式,它将为您检测要使用的正确T(调用Evil-of-T)。
注意:你需要一个额外的方法的唯一原因是确保它不会递归地解析回自己,因为名字是相同的。
是的,您需要获得泛型方法定义。之后,您可以使用MethodInfo.MakeGenericMethod
来构造泛型方法。
比如:
MethodInfo genericMethodDefinition = GetType()
.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
.Where(method => method.IsGenericMethod && method.Name == "GetPersisterFor")
.First();
// OR
MethodInfo genericMethodDefinition = GetType().GetMethod("GetPersisterFor",
BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
// THEN
MethodInfo genericMethod = genericMethodDefinition.MakeGenericMethod(entity.GetType());
genericMethod.Invoke(this, null);
由于泛型和非泛型方法具有相同的名称,因此您必须遍历类的所有方法以找到合适的方法,然后调用它:
public IPersister GetPersisterFor(IEntity entity)
{
MethodInfo getPersisterForGenericMethod =
GetType().GetMethods()
// iterate over all methods to find proper generic implementation
.Single(methodInfo => methodInfo.Name == "GetPersisterFor" && methodInfo.IsGenericMethod)
// supply it with generic type parameter
.MakeGenericMethod(entity.GetType());
// invoke it
return getPersisterForGenericMethod.Invoke(this, null) as IPersister;
}
public IPersister GetPersisterFor<TEntity>() where TEntity : IEntity
{
return null;
}
ps:完整的源代码在gist.github