Comment accéder à la propriété générique sans connaître le type générique fermé

J’ai un type générique comme suit

public class TestGeneric { public T Data { get; set; } public TestGeneric(T data) { this.Data = data; } } 

Si j’ai maintenant un object (qui provient d’une source externe) dont je sais qu’il est de type TestGeneric fermé , mais que je ne connais pas le TypeParameter T. Maintenant, je dois accéder aux données de mon objet. . Le problème est que je ne peux pas lancer l’objet, car je ne sais pas exactement à qui TestGeneric est fermé.

j’utilise

 // thx to http://stackoverflow.com/questions/457676/c-reflection-check-if-a-class-is-derived-from-a-generic-class private static bool IsSubclassOfRawGeneric(Type rawGeneric, Type subclass) { while (subclass != typeof(object)) { var cur = subclass.IsGenericType ? subclass.GetGenericTypeDefinition() : subclass; if (rawGeneric == cur) { return true; } subclass = subclass.BaseType; } return false; } 

pour être sûr, mon object est du type générique. Le code en question est le suivant:

 public static void Main() { object myObject = new TestGeneric("test"); // or from another source if (IsSubclassOfRawGeneric(typeof(TestGeneric), myObject.GetType())) { // the following gives an InvalidCastException // var data = ((TestGeneric)myObject).Data; // if i try to access the property with reflection // i get an InvalidOperationException var dataProperty = typeof(TestGeneric).GetProperty("Data"); object data = dataProperty.GetValue(myObject, new object[] { }); } } 

J’ai besoin des données quel que soit leur type (eh bien, si je pouvais demander leur type à l’aide de GetType (), ce serait bien, mais pas nécessaire), car je veux simplement le vider au format XML avec ToSsortingng ().

Aucune suggestion? Merci

Avant de pouvoir accéder à ses membres génériques, vous devez connaître le type fermé d’une classe générique. L’utilisation de TestGeneric<> vous donne la définition de type ouvert, qui ne peut pas être appelée sans spécifier les arguments génériques.

Le moyen le plus simple d’obtenir la valeur de la propriété est de réfléchir directement au type fermé utilisé:

 public static void Main() { object myObject = new TestGeneric("test"); // or from another source var type = myObject.GetType(); if (IsSubclassOfRawGeneric(typeof(TestGeneric<>), type)) { var dataProperty = type.GetProperty("Data"); object data = dataProperty.GetValue(myObject, new object[] { }); } } 

Oh, les stackies … pourquoi personne ne m’a indiqué le type dynamic ? C’est l’exemple parfait d’utilisation qui rend le code beaucoup plus lisible:

 dynamic dynObject = myObject; object data = dynObject.Data; 

Ahh, désolé pour ça. Ce fut une simple erreur, la version générique fonctionne, bien sûr il faut lire

 var dataProperty = myObject.GetType().GetProperty("Data"); object data = dataProperty.GetValue(myObject, new object[] { }); 

À partir de la version 6, nous pouvons utiliser nameof pour améliorer légèrement la réponse de Paul:

 public static void Main() { object myObject = new TestGeneric("test"); // or from another source var type = myObject.GetType(); if (IsSubclassOfRawGeneric(typeof(TestGeneric<>), type)) { var dataProperty = type.GetProperty(nameof(TestGeneric.Data)); object data = dataProperty.GetValue(myObject); } } 

Notez que le remplacement de type.GetProperty("Data") par type.GetProperty(nameof(TestGeneric.Data)) vous procure une sécurité de compilation (donc sans doute meilleure que l’utilisation de la méthode dynamic ).

Utiliser aussi object comme paramètre de type est simplement un moyen d’accéder à la propriété et n’a aucun effet secondaire ou signification particulière.