c#反射匹配类型列表<其中T是subclass (Foo)

本文关键字:subclass Foo 其中 反射 类型 列表 | 更新日期: 2023-09-27 18:17:26

我有一个包含List<T>属性的类。在这些属性中,T属于继承自类的类,比如Foo。

public class Foo {}
public class MyTypeA : Foo {}
public class MyTypeB : Foo {}
// Not : Foo
public class MyTypeC {}
public class Bar 
{
    // I can Match these
    public MyTypeA PropA { get; set; }
    public MyTypeB PropB { get; set; }
    // How can I match these based on IsSubclassOf(Foo)
    public List<MyTypeA> PropListA { get; set; }
    public List<MyTypeB> PropListB { get; set; }
    // Do not match the props below
    public MyTypeC PropC { get; set; }
    public List<MyTypeC> PropListC { get; set; }
    public List<string> PropListString { get; set; }
}    

我已经成功匹配了Foo子类的属性,如下所示。

foreach (var oProp in T.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
    // Find Prop : Foo
    if( oProp.PropertyType.IsSubclassOf( typeof(Foo) ) )
    {
        // Add Property to dictionary
        aPropInheritType.Add(
            oProp.Name, 
            oProp
        );
    }
    // Match List<T>  where T : Foo
    // How do I test for Generic List that's Type T is a subclass 
    // of the class Foo ?
}

我看到有一些类型类的泛型属性,但还没有能够得到泛型列表的类型,然后对IsSubclassOf(Foo)进行测试。

c#反射匹配类型列表<其中T是subclass (Foo)

要测试一个属性是否有返回类型List<T>,使用下一个代码:

Type returnType = oProp.PropertyType;
if(returnType.IsGenericType && 
   returnType.GetGenericTypeDefinition() == typeof(List<>) &&
   typeof(Foo).IsAssignableFrom(returnType.GetGenericArguments()[0]))
{
   //property is of type List<T>, where T is derived from Foo
}

这是我从微软框架中偷来的一个小宝石(我想它在EF二进制文件中)。

    private static Type GetTypeOfList(PropertyInfo changedMember)
    {
        var listType = from i in changedMember.PropertyType.GetInterfaces()
                       where i.IsGenericType
                       let generic = i.GetGenericTypeDefinition()
                       where generic == typeof (IEnumerable<>)
                       select i.GetGenericArguments().Single();
        return listType.SingleOrDefault();
    }

你只需要测试

    Type listType = ...
    var tInListType = GetTypeOfList(listType);
    return tInListType.IsAssignableFrom(typeof(Foo));