web-dev-qa-db-fra.com

Comment déterminer les types de propriétés à l'aide de la réflexion?

Comment pourrais-je tester une propriété d'un type pour voir s'il s'agit d'un type spécifié?

EDIT: Mon objectif est d'examiner un assembly pour voir si l'un des types de cet assembly contient des propriétés qui sont MyType (ou héritées de MyType).

Voici la piste que j'ai descendue ...

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");

Ceci est compilé avec l'avertissement CS0184: L'expression donnée n'est jamais du type fourni ('MyType')

32
Ed Guiness

Quel type êtes-vous intéressé? Le type de retour de la méthode/propriété/événement, etc.?

Si tel est le cas, je ne pense pas qu'il y ait quelque chose dans MemberInfo qui vous permette de le résoudre directement - vous devrez lancer et utiliser MethodInfo.ReturnType, PropertyInfo.PropertyType, FieldInfo.FieldType, EventInfo.EventHandlerType et tous les autres que j'ai oubliés. (N'oubliez pas que les types eux-mêmes peuvent être des membres. Vous ne savez pas vraiment ce que vous voudrez faire d'eux!)

EDIT: Si vous souhaitez savoir si un type spécifique représente MyType ou une sous-classe, utilisez Type.IsAssignableFrom :

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

EDIT: Maintenant que nous savons que vous voulez des propriétés, rien de plus simple: utilisez GetProperties au lieu de GetMembers. J'aime faire de la réflexion avec 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);
}

Si vous n'êtes pas fan de 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");

Notez que vous voudrez peut-être spécifier des indicateurs de liaison pour obtenir des propriétés non publiques, etc.

55
Jon Skeet

Ok, peut-être me manque quelque chose de stupide, mais ne devrait-il pas être:

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

???

48
BFree

Il existe plusieurs façons de tester le type d'un objet:

1) Utilisez l'opérateur is /:

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

2) Utilisez l'opérateur comme :

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

3) Utilisez typeof () et GetType () [3 variantes]:

// #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);
}
2
rivy

Je pense que vous avez besoin de quelque chose comme ça:

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;
    }
}
1
Paolo Tedesco

Tu recherches:

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

droite ?

1
Alexander

C'est un raccourci

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

Vous devriez utiliser is lorsque vous comparez une instance de quelque chose avec un type explicitement écrit:

Department sales = new Department("Sales");

Debug.Assert(sales is Department);

Vous devez utiliser typeof lorsque vous souhaitez comparer 2 types et que vous ne pouvez pas écrire le type explicitement:

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

Utiliser is prendra en compte l'héritage, typeof wont.

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
}

Si vous voulez comparer 2 types et prendre en compte l'héritage, vous pouvez utiliser IsAssignableFrom:

Debug.Assert(typeof(Animal).IsAssignableFrom(typeof(Dog))); // true
0
PeteGO