C# 如何从c中的派生类型获取泛型类型的泛型参数类型#
谢谢,我有:C# 如何从c中的派生类型获取泛型类型的泛型参数类型#,c#,reflection,C#,Reflection,谢谢,我有: class MyBase<T1, T2>{} class MyConcreteBase<T2> : MyBase<ConcreteType1, T2>{} class MyConcrete1 : MyConcreteBase<ConcreteType2>{} class MyConcrete2 : MyBase<ConcreteType1, ConcreteType2>{} 类MyBase{} 类MyConcret
class MyBase<T1, T2>{}
class MyConcreteBase<T2> : MyBase<ConcreteType1, T2>{}
class MyConcrete1 : MyConcreteBase<ConcreteType2>{}
class MyConcrete2 : MyBase<ConcreteType1, ConcreteType2>{}
类MyBase{}
类MyConcreteBase:MyBase{}
类MyConcrete1:MyConcreteBase{}
类MyConcrete2:MyBase{}
如果我有MyConcrete1
或MyConcrete2
或MyConcreteBase
的实例,或者从MyBase
派生的任何其他类型实例,如何获取T1
和T2
的类型
我现在这样做的方式是通过继承链使用.GetType().BaseType
而BaseType.Name.StartsWith(“MyBase”)
然后使用.GetGenericArguments()
它正在工作,但我对它不满意,尤其是.StartsWith(“MyBase”)
部分
有人有其他建议吗?是的,不要使用字符串解析。您可以简单地使用
BaseType.IsAssignableFrom(typeof(MyBase))
(可能需要反转BaseType
和MyBase
——我总是感到困惑)
将类型公开为基类中的属性也可能更容易,例如:
public Type T1_Type { get { return typeof(T1); } }
public Type T2_Type { get { return typeof(T2); } }
我不得不问,为什么需要提取这些类型参数?这对我来说是一种代码味道
编辑:我应该补充一点,您不能像使用泛型一样使用
IsAssignableFrom
。请查看此答案以获得完整的解决方案:如果您能告诉我们更多关于您想要实现的目标,那就太好了。猜猜你的想法是什么,我会说:只要BaseType
不是null
,就可以遍历整个继承链。然后检查每个类型是否为泛型,如果是,则调用getgenericalarguments
。应该是几个谓词和一两个LINQ表达式的问题。你的意思是: 我想不出什么聪明的办法,所以我可能会这么做:
class MyBase<T1, T2> {
protected Type GetT1() { return typeof(T1); }
protected Type GetT2() { return typeof(T2); }
}
类MyBase{
受保护类型GetT1(){return typeof(T1);}
受保护类型GetT2(){return typeof(T2);}
}
您可以在继承层次结构中查找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;
}
}
}
var type=c.GetType();
类型baseType=类型;
while(null!=(baseType=baseType.baseType))
{
if(baseType.IsGenericType)
{
var generic=baseType.GetGenericTypeDefinition();
if(generic==typeof(MyBase))
{
var genericTypes=baseType.GetGenericArguments();
//genericTypes具有用于构造baseType的类型参数。
打破
}
}
}
这里有一个函数,它将接受任何类型(假设它有一个带有泛型参数的基类),并返回该实例基类的泛型参数的类型:
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();
}
public类型[]BaseGenericTypes(T实例)
{
类型instanceType=instance.GetType();
类型objectType=newobject().GetType();
while(instanceType.BaseType!=objectType)
{
instanceType=instanceType.BaseType;
}
返回instanceType.GetGenericArguments();
}
这个方法的好处是,您不需要知道任何关于基类或其任何后续派生类的信息。这是我答案中的一个快速下降投票人。@BoltClock这是对错误问题的错误答案。@siride:的确如此。我只是在评论它有多快:)@siride-我想这仍然是“如果我有MyConcrete1或MyConcrete2或MyConcreteBase实例或任何其他从MyBase派生的类型实例,我如何获得T1和T2类型”的答案,但他已经知道这一部分。这是算法的另一部分,他需要帮助。这就好像有人问如何解析数学表达式,但语法有问题,而你建议他使用Regex类将内容分解为标记。技术上是正确的,但对眼前的问题没有帮助。@siride-我不明白他在看什么for@siride-我需要它,因为我的MVC应用程序中有通用ReportController,并且我在那里有动作显示(字符串reportName)。然后是ReportBase,然后是WhateverReport:ReportBase,然后是YearlyWhateverReport:WhateverReport。。。等等因此,我需要知道tenty的类型,以便将其传递到存储库,并获取needet IQueryable以将其提供给ReportBase.Generate(IQueryable entityQuery)@qrow,然后我认为在基类中将类型作为属性公开是最好的选择。它也比使用反射快得多。@siride你可能是对的,这可能是最简单的解决方案,不知何故,我对那些泛型操作使用了太多反射,所以我没有考虑只在基础上公开泛型arg类型class@siride我回来工作了,终于可以测试这里建议的解决方案了。我意识到在MyBase中公开类型对我来说是不可修改的,因为我不知道派生对象的类型,并且我不能做类似((MyBase)report)的事情。。。所以也许我唯一的选择就是反射,毕竟我最终使用了动态而不是对象,并且能够调用T1_类型。所以我坚持这个解决方案,Iride也问了这个的目的,所以你们可以在那个里查看我的解释。