代码之家  ›  专栏  ›  技术社区  ›  Ed Guiness

如何使用反射确定属性类型?

  •  38
  • Ed Guiness  · 技术社区  · 17 年前

    我如何测试一个类型的属性,看看它是否是指定的类型?

    编辑:我的目标是检查一个程序集,看看该程序集中的任何类型是否包含MyType(或继承自MyType)的属性。

    这是我走过的路。..

    AssemblyName n = new AssemblyName();
    n.CodeBase = "file://" + dllName;
    Assembly a = AppDomain.CurrentDomain.Load(n);
    
    foreach (Type t in a.GetTypes())
        foreach (PropertyInfo pi in t.GetProperties())
            if ( pi.PropertyType is MyType ) // warning CS0184
                Console.WriteLine("Found a property that is MyType");
    

    这与警告CS0184一起编译:给定的表达式从不属于提供的('MyType')类型

    8 回复  |  直到 17 年前
        1
  •  59
  •   Jon Skeet    17 年前

    你对哪种类型感兴趣?方法/属性/事件等的返回类型?

    如果是这样,我认为里面什么都没有 MemberInfo 为了让你直接掌握它,你需要施放和使用 MethodInfo.ReturnType , PropertyInfo.PropertyType , FieldInfo.FieldType , EventInfo.EventHandlerType 还有我忘记的其他人。(记住,类型本身也可以是成员。不确定你想用它们做什么!)

    编辑:如果你对特定的Type是代表MyType还是某个子类感兴趣,那么使用 Type.IsAssignableFrom :

    if (typeof(MyType).IsAssignableFrom(type))
    

    编辑:现在我们知道您需要属性,使用GetProperties而不是GetMembers很容易。我喜欢用LINQ做反思:

    var query = from type in assembly.GetTypes()
                from property in type.GetProperties()
                where typeof(MyType).IsAssignableFrom(property.PropertyType)
                select new { Type=type, Property=property };
    
    foreach (var entry in query)
    {
        Console.WriteLine(entry);
    }
    

    如果你不喜欢LINQ:

    foreach (Type t in a.GetTypes())
        foreach (PropertyInfo pi in t.GetProperties())
            if (typeof(MyType).IsAssignableFrom(pi.PropertyType))
                Console.WriteLine("Found a property that is MyType");
    

    请注意,您可能希望指定绑定标志以获取非公共属性等。

        2
  •  48
  •   BFree    17 年前

    好吧,也许我错过了一些愚蠢的东西,但不应该是:

    if ( pi.PropertyType == typeof(MyType ))
    

    ???

        3
  •  2
  •   rivy    17 年前

    有多种方法可以测试对象的类型:

    1) 使用 操作员:

    if (anObject is MyType) {
    // anObject is MyType or a derived class
    ... 
    }
    

    2) 使用 操作员:

    MyType newObject = anObject as MyType;
    if (newObject != null ) {
    // newObject is anObject cast to MyType
    ...
    }
    

    3) 使用typeof()和GetType()[3种变体]:

    // #1
    if (typeof(MyType) == anObject.GetType()) {
    // anObject is a MyType
    ...
    }
    
    //#2
    public static bool IsType(object obj, string type)
    {// modified from Visual C# 2005 Recipes {Apress}
    // Get the named type, use case-insensitive search, throw
    // an exception if the type is not found.
    Type t = Type.GetType(type, true, true);
    return t == obj.GetType();
    }
    
    //#3
    public static bool IsTypeOrSubclass(object obj, string type)
    {// modified from Visual C# 2005 Recipes {Apress}
    // Get the named type, use case-insensitive search, throw
    // an exception if the type is not found.
    Type t = Type.GetType(type, true, true);
    return t == obj.GetType() || obj.GetType().IsSubclassOf(t);
    }
    
        4
  •  1
  •   Alexander    17 年前

    您正在寻找:

    if (typeof(mi) is MyType) { ... }
    

    正确的

        5
  •  1
  •   Paolo Tedesco    17 年前

    我认为你需要这样的东西:

    using System;
    using System.Reflection;
    
    namespace ConsoleApplication1{
        class Class1{
    
            static bool checkType(Type propertyType,Type myType){
                if (propertyType == myType){
                    return true;
                }
                Type test = propertyType.BaseType;
                while (test != typeof(Object)){
                    if (test == myType){
                        return true;
                    }
                    test = test.BaseType;
                }
                return false;
            }
    
            [STAThread]
            static void Main(string[] args){
                Assembly a = Assembly.GetExecutingAssembly();
                foreach (Type t in a.GetTypes()){
                    Console.WriteLine("Type: {0}",t.Name);
                    foreach (PropertyInfo p in t.GetProperties()){
                        if (checkType(p.PropertyType,typeof(MyType))){
                            Console.WriteLine("  Property: {0}, {1}",p.Name,p.PropertyType.Name);
                        }
                    }
                }
            }
        }
    
        class MyType{
        }
    
        class MyType2 : MyType{
        }
    
        class TestType
        {
            public MyType mt{
                get{return _mt;}
                set{_mt = value;}
            }
            private MyType _mt;
            public MyType2 mt2
            {
                get{return _mt2;}
                set{_mt2 = value;}
            }
            private MyType2 _mt2;
        }
    }
    
        6
  •  1
  •   vlr    13 年前

    这个来自另一个类似问题的例子大大简化了我的理解

    If p.PropertyType Is GetType(String) Then

        7
  •  0
  •   PeteGO    13 年前

    你应该使用 is 当将某物的实例与显式编写的类型进行比较时:

    Department sales = new Department("Sales");
    
    Debug.Assert(sales is Department);
    

    当你想比较两种类型并且不能显式地编写类型时,你应该使用typeof:

    private void CheckType(Type t)
    {
        Debug.Assert(typeof(Department) == t);
    }
    

    使用 将考虑继承, typeof 习惯于。

    public class Animal { }
    public class Dog : Animal { }
    
    public void Test()
    {
        Dog d = new Dog();
    
        Debug.Assert(d is Animal); // true
    
        Debug.Assert(typeof(Dog) == typeof(Animal); // false
    }
    

    如果你想比较两种类型并考虑继承性,你可以使用 IsAssignableFrom :

    Debug.Assert(typeof(Animal).IsAssignableFrom(typeof(Dog))); // true
    
        8
  •  0
  •   Sabarinathan Arthanari    12 年前

    这是捷径

    property.PropertyType.IsGenericType && (typeof(ICollection<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition()))
    && typeof(<YourType>).IsAssignableFrom(property.PropertyType.GenericTypeArguments[0])
    
    推荐文章