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
Notez que le remplacement de type.GetProperty("Data")
par type.GetProperty(nameof(TestGeneric
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.