我可以使用反射中的类型作为类型参数吗?例如。我想根据传递的对象选择一个持久性:
IPersister GetPersisterFor(IEntity entity)
{
return GetPersisterFor<entity.GetType()>(); // <-- this cannot be compiled
}
IPersister GetPersisterFor<TEntity>() where TEntity : IEntity
{
//some logic to get persister...
}
答案 0 :(得分:4)
只能通过反思;您需要使用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)。
注意:您需要额外方法的唯一原因是确保它不会递归地解析回自身,因为名称是相同的。
答案 1 :(得分:1)
是的,您需要获取通用方法定义。
之后,您可以使用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);
答案 2 :(得分:1)
因为泛型和非泛型方法都具有相同的名称,所以必须迭代所有类的方法以找到合适的方法,然后调用它:
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
提供的完整源代码