简体   繁体   English

如何从 c# 中的派生类型获取泛型类型的泛型参数类型

[英]How to get generic argument types of generic type from derived type in c#

Supose i have:假设我有:

class MyBase<T1, T2>{}

class MyConcreteBase<T2> : MyBase<ConcreteType1, T2>{}

class MyConcrete1 : MyConcreteBase<ConcreteType2>{}

class MyConcrete2 : MyBase<ConcreteType1, ConcreteType2>{}

How do i get types of T1 and T2 if i have instance of MyConcrete1 or MyConcrete2 or MyConcreteBase or any other instance of type derived from MyBase<T1, T2>如果我有MyConcrete1MyConcrete2MyConcreteBase的实例或派生自MyBase<T1, T2>的任何其他类型实例,我如何获得T1T2的类型

The way i do it now is i'm "getting up" by inheritance chain using .GetType().BaseType while BaseType.Name.StartsWith("MyBase") and then using .GetGenericArguments()我现在这样做的方式是我通过 inheritance 链“起床”,使用.GetType().BaseTypeBaseType.Name.StartsWith("MyBase")然后使用.GetGenericArguments()

It is working, but i'm not satisfied with it, especially .StartsWith("MyBase") part.它正在工作,但我对此并不满意,尤其是.StartsWith("MyBase")部分。

Anyone have other suggestions?有人有其他建议吗?

You can walk up the inheritance hierarchy and look for a GenericType, which is constructed from BaseType<,> .您可以向上走 inheritance 层次结构并查找由BaseType<,>构造的 GenericType。 Try:尝试:

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;
        }
    }
}   

Yeah, don't use string parsing.是的,不要使用字符串解析。 You can simply use BaseType.IsAssignableFrom(typeof(MyBase<,>)) (might have to reverse the BaseType and MyBase<,> -- I always get that confused).您可以简单地使用BaseType.IsAssignableFrom(typeof(MyBase<,>)) (可能必须颠倒BaseTypeMyBase<,> - 我总是感到困惑)。

It might also be easier to expose the types as properties in your base class, eg:将类型公开为基础 class 中的属性也可能更容易,例如:

public Type T1_Type { get { return typeof(T1); } }
public Type T2_Type { get { return typeof(T2); } }

I do have to ask, why do you need to extract these type parameters?我不得不问,为什么需要提取这些类型参数? This is a code smell to me.这对我来说是一种代码味道。

EDIT: I should add that you can't use IsAssignableFrom as is for generics.编辑:我应该补充一点,你不能像IsAssignableFrom一样使用 IsAssignableFrom。 Check out this answer for a full solution: How To Detect If Type is Another Generic Type查看此答案以获取完整解决方案: 如何检测类型是否为另一种通用类型

Would be good if you would tell us a bit more about what you want to achive.如果您能告诉我们更多关于您想要实现的目标,那就太好了。 Guessing what you idea is, I would say: Just walk the complete inheritance chain as long as BaseType is not null .猜猜你的想法是什么,我想说:只要BaseType不是null ,就走完整的 inheritance 链。 And then check for each type if it's generic and if yes, call GetGenericArguments .然后检查每种类型是否是通用的,如果是,请调用GetGenericArguments Should be a matter of a few predicates and one or two LINQ expressions.应该是几个谓词和一两个 LINQ 表达式的问题。

I can't think of anything clever, so I'd probably just do this:我想不出任何聪明的东西,所以我可能会这样做:

class MyBase<T1, T2> {
    protected Type GetT1() { return typeof(T1); }
    protected Type GetT2() { return typeof(T2); }
}

Here is a function that will accept any type (assuming it has a base class with generic parameters) and return the types of that instance's base class's generic parameters:这是一个 function 将接受任何类型(假设它具有带有泛型参数的基本 class)并返回该实例的基类的泛型参数的类型:

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();
    }

The nice thing about this method is you don't need to know anything about the base class or any of its subsequent derived classes.这种方法的好处是您不需要知道任何关于基础 class 或其任何后续派生类的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM