Comment utiliser la reflection pour obtenir une méthode d’extension sur un type générique

De diverses sources sur les sites Web, j’ai glané cette fonction suivante:

public static Nullable TryParseNullable(this Nullable t, ssortingng input) where T : struct { if (ssortingng.IsNullOrEmpty(input)) return default(T); Nullable result = new Nullable(); try { IConvertible convertibleSsortingng = (IConvertible)input; result = new Nullable((T)convertibleSsortingng.ToType(typeof(T), CultureInfo.CurrentCulture)); } catch (InvalidCastException) { } catch (FormatException) { } return result; } 

Je l’ai transformé en une méthode d’extension, et cela fonctionne très bien si je l’appelle directement:

 int? input = new int?().TryParseNullable("12345"); 

Mon problème survient lorsque j’essaie de l’appeler en utilisant la reflection dans le contexte d’une autre fonction générique. SO regorge de réponses décrivant comment obtenir les informations MethodInfo des méthodes génériques et des méthodes statiques, mais je n’arrive pas à les assembler correctement.
J’ai correctement déterminé que le type générique passé est lui-même un type générique ( Nullable ), je souhaite maintenant utiliser la reflection pour appeler la méthode d’extension TryParseNullable sur la Nullable :

 public static T GetValue(ssortingng name, T defaultValue) { ssortingng result = getSomeSsortingngValue(name); if (ssortingng.IsNullOrEmpty(result)) return defaultValue; try { if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(Nullable)) { MethodInfo methodInfo; //using the TryParse() of the underlying type works but isn't exactly the way i want to do it //------------------------------------------------------------------------------------------- NullableConverter nc = new NullableConverter(typeof(T)); Type t = nc.UnderlyingType; methodInfo = t.GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, new[] { typeof(string), t.MakeByRefType() }, null); if (methodInfo != null) { var inputParameters = new object[] { result, null }; methodInfo.Invoke(null, inputParameters); return (T) inputParameters[1]; } //start of the problem area //------------------------- Type ttype = typeof(T); //this works but is undesirable (due to reference to class containing the static method): methodInfo = typeof(ParentExtensionsClass).GetMethod("TryParseNullable", BindingFlags.Public | BindingFlags.Static); if (methodInfo != null) Console.WriteLine(methodInfo); //standard way of getting static method, doesn't work (GetMethod() returns null): methodInfo = ttype.GetMethod("TryParseNullable", BindingFlags.Public | BindingFlags.Static); if (methodInfo != null) Console.WriteLine(methodInfo); //Jon Skeet's advised method, doesn't work in this case (again GetMethod() returns null): //(see footnote for link to this answer) methodInfo = ttype.GetMethod("TryParseNullable"); methodInfo = methodInfo.MakeGenericMethod(ttype); if (methodInfo != null) Console.WriteLine(methodInfo); //another random attempt (also doesn't work): methodInfo = ttype.GetMethod("TryParseNullable", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, new[] { typeof(string) }, null); if (methodInfo != null) Console.WriteLine(methodInfo); } // if we get this far, then we are not handling the type yet throw new ArgumentException("The type " + defaultValue.GetType() + " is not yet supported by GetValue.", "T"); } catch (Exception e) { [snip] } } 

Est-ce que quelqu’un peut me sortir de ma misère?
Le typeof(T) renvoie les informations de type correctes, je typeof(T) que je l’utilise peut-être un peu de manière incorrecte avec l’appel GetMethod() ou je n’ai pas spécifié les bons parameters avec l’appel de GetMethod() .

1. Lien vers la réponse référencée de Jon Skeet

Le problème est que les méthodes d’extension ne modifient pas le type qu’elles “étendent”. En réalité, le compilateur traduit de manière transparente tous les appels qui semblent être effectués sur l’object en question en appels à votre méthode statique.

c’est à dire.

 int? input = new int?().TryParseNullable("12345"); // becomes... int? input = YourClass.TryParseNullable(new int?(), "12345"); 

À partir de là, il devient évident pourquoi il ne se manifeste pas par reflection. Cela explique également pourquoi vous devez avoir une directive using pour l’espace de nom où YourClass est définie pour que les méthodes d’extension soient visibles par le compilateur. Pour ce qui est de savoir comment obtenir ces informations, je ne suis pas sûr qu’il soit possible de parcourir tous les types déclarés (peut-être une liste filtrée de classes intéressantes, si vous connaissez ce type d’informations à la compilation). pour les méthodes statiques sur lesquelles ExtensionMethodAtsortingbute ( [ExtensionMethod] ) est défini, puis essayez d’parsingr MethodInfo pour que la liste de parameters détermine si elles fonctionnent avec Nullable<> .