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也问了这个的目的,所以你们可以在那个里查看我的解释。