【问题标题】:How can I determine property types using reflection?如何使用反射确定属性类型?
【发布时间】:2014-03-20 14:28:57
【问题描述】:

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

编辑:我的目标是检查程序集以查看该程序集中的任何类型是否包含 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: The given expression never of the provided ('MyType') type

【问题讨论】:

    标签: c# .net reflection


    【解决方案1】:

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

    如果是这样,我认为 MemberInfo 中没有任何内容可以让您直接使用它 - 您需要转换并使用 MethodInfo.ReturnTypePropertyInfo.PropertyTypeFieldInfo.FieldTypeEventInfo.EventHandlerType 和任何其他我已经忘记了。 (请记住,类型本身可以是成员。不确定您要对它们做什么!)

    编辑:如果您对特定类型是否代表 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");
    

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

    【讨论】:

    • 我应该说“属性”而不是“成员”。我已经更新了这个问题,希望现在更清楚了。
    • @Jon Skeet:无关:你看过 FinalBuilder 广告吗?很有趣!
    • @Mitch:是的。他们也很友好地先问我是否可以。
    【解决方案2】:

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

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

    ???

    【讨论】:

    • 如果你的类型是通用的(例如 DbSet)你可以试试这个.. if (pi.PropertyType.IsGenericType && pi.PropertyType.GetGenericTypeDefinition() == typeof(DbSet) ) { ... }
    • 这比接受的答案更有意义。 type.IsAssignableFrom() 看起来(我自己没有测试过)如果类型继承自另一个基类或接口,它可以匹配另一个类型。例如:List 可以是 IsAssignableFrom IEnumerable,反之亦然。
    【解决方案3】:

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

    1) 使用 is 运算符:

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

    2) 使用 as 运算符:

    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】:

      您正在寻找:

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

      对吗?

      【讨论】:

      • 这行不通,因为 typeof(mi) 的类型是 Type,而不是 MyType
      【解决方案5】:

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

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

      【讨论】:

      • 我得到的警告是 CS0184: The given expression is never of the provided type
      • 那是因为它的类型是System.Type...检查我的代码,希望它有帮助。
      【解决方案6】:

      this example from the other similar question大大简化了我的理解

      If p.PropertyType Is GetType(String) Then

      【讨论】:

        【解决方案7】:

        在将某事物的实例与明确写入的类型进行比较时,您应该使用is

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

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

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

        使用is 会考虑继承,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】:

          这是捷径

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-02-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-06-05
            • 1970-01-01
            • 2017-04-24
            • 1970-01-01
            相关资源
            最近更新 更多