我有:
class MyBase<T1, T2>{}
class MyConcreteBase<T2> : MyBase<ConcreteType1, T2>{}
class MyConcrete1 : MyConcreteBase<ConcreteType2>{}
class MyConcrete2 : MyBase<ConcreteType1, ConcreteType2>{}
如果我有T1
或T2
或MyConcrete1
的实例或从中派生的任何其他类型的实例,我如何获得MyConcrete2
和MyConcreteBase
的类型MyBase<T1, T2>
我现在这样做的方式是在.GetType().BaseType
使用BaseType.Name.StartsWith("MyBase")
然后使用.GetGenericArguments()
它正在运作,但我对此并不满意,特别是.StartsWith("MyBase")
部分。
有人有其他建议吗?
答案 0 :(得分:3)
您可以走继承层次结构并查找GenericType,它是从BaseType<,>
构建的。尝试:
var type = c.GetType();
Type baseType = type;
while(null != (baseType = baseType.BaseType))
{
if (baseType.IsGenericType)
{
var generic = baseType.GetGenericTypeDefinition();
if (generic == typeof(MyBase<,>))
{
var genericTypes = baseType.GetGenericArguments();
// genericTypes has the type argument used to construct baseType.
break;
}
}
}
答案 1 :(得分:2)
是的,不要使用字符串解析。您可以简单地使用BaseType.IsAssignableFrom(typeof(MyBase<,>))
(可能必须撤销BaseType
和MyBase<,>
- 我总是让它感到困惑。)
将类型公开为基类中的属性也可能更容易,例如:
public Type T1_Type { get { return typeof(T1); } }
public Type T2_Type { get { return typeof(T2); } }
我不得不问,为什么需要提取这些类型参数?这对我来说是一种代码味道。
编辑:我应该补充一点,你不能使用IsAssignableFrom
作为泛型。查看此答案以获得完整的解决方案:How To Detect If Type is Another Generic Type
答案 2 :(得分:0)
如果您能告诉我们更多关于您想要实现的内容,那将会很好。猜测你的想法是什么,我会说:只要BaseType
不是null
,就走完整个继承链。然后检查每种类型是否通用,如果是,请致电GetGenericArguments
。应该是一些谓词和一个或两个LINQ表达式。
答案 3 :(得分:0)
我想不出任何聪明的东西,所以我可能只是这样做:
class MyBase<T1, T2> {
protected Type GetT1() { return typeof(T1); }
protected Type GetT2() { return typeof(T2); }
}
答案 4 :(得分:0)
这是一个接受任何类型的函数(假设它有一个带有泛型参数的基类)并返回该实例的基类的泛型参数的类型:
public Type[] BaseGenericTypes<T>(T instance)
{
Type instanceType = instance.GetType();
Type objectType = new object().GetType();
while (instanceType.BaseType != objectType)
{
instanceType = instanceType.BaseType;
}
return instanceType.GetGenericArguments();
}
这个方法的好处是你不需要知道任何关于基类或其任何后续派生类的信息。
答案 5 :(得分:-1)