Considérons le code suivant:
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
MethodInfo methodInfo = typeof(Program).GetMethod("Baz"); // Foo Baz(){return foo;}
Type typeFoo = methodInfo.ReturnType;
var result = (typeFoo)objFoo;
Dois-je faire de la magie avec typeFoo
pour obtenir le résultat?
Non :-)
Cas 1:
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Foo result = (Foo)objFoo;
Aucune réflexion ici, car vous connaissez le type Foo
au moment de la compilation.
Cas 2: interfaces. Normalement, le meilleur ... Vous ne savez pas ce que renvoie exactement MakeFoo
, mais vous savez que c'est une interface IFoo
...
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
IFoo result = (IFoo)objFoo;
Cas 3: vous n'êtes pas sûr que MakeFoo
renvoie Foo
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
if (objFoo is Foo)
{
Foo result = (Foo)objFoo;
}
ou similaire
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Foo foo = objFoo as Foo;
if (foo != null)
{
// use foo
}
Cas 4: type Foo
est complètement inconnu de votre programme. Vous n'avez pas de classe Foo
référençable ...
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Type typeFoo = objFoo.GetType(); // You should check for null values before!
// and now?
dynamic foo = objFoo;
// because you know that foo can Quack(1, 2, 3)!
string result = foo.Quack(1, 2, 3);
// note that it will explode with a RuntimeBinderException if there is no
// string Quack(int, int, int) method!
la dynamic
utilise en interne la réflexion. Vous pouvez utiliser la réflexion directement pour obtenir la méthode Quack
et l'appeler
Cas 5: en tant que cas 4, mais en utilisant directement la réflexion:
object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Type typeFoo = objFoo.GetType(); // You should check for null values before!
MethodInfo mi = type.GetMethod("Quack"); // You should check if the Quack method
// exists
string result = (string)mi.Invoke(objFoo, new object[] { 1, 2, 3 });
ou, avec quelques vérifications, si vous n'êtes pas sûr, foo
peut Quack
correctement:
MethodInfo mi = type.GetMethod("Quack",
BindingFlags.Instance | BindingFlags.Public,
null,
new[] { typeof(int), typeof(int), typeof(int) },
null);
if (mi != null && typeof(string).IsAssignableFrom(mi.ReturnType))
{
string result = (string)mi.Invoke(objFoo, new object[] { 1, 2, 3 });
}
Case -Infinity: type Foo
est complètement inconnu de votre programme. Vous n'avez pas de classe Foo
référençable. Vous n'avez pas d'interface IFoo
. Vous ne savez même pas ce qu'est une Foo
, vous savez seulement que c'est une classe (ou peut-être que c'est une struct
encadrée, mais cela ne change pas de votre point de vue ... Ça ne peut pas être une interface
car fin il doit toujours y avoir une class
/struct
derrière chaque interface
). Vous ne connaissez pas ses méthodes, ses champs, ses propriétés (car vous ne savez pas ce que est Foo
).
Même si vous pouvez lancer une object
dans cette classe inconnue, que pouvez-vous faire? Vous ne pouvez pas avoir de méthodes dans votre code qui l'acceptent comme paramètre/valeur de retour, car si vous aviez quelque part:
int INeedFoo(Foo par) { return 0; }
alors clairement vous sauriez Foo
. La bibliothèque .NET ne peut pas avoir de méthodes qui l'acceptent comme paramètre/valeur de retour, car si c'était le cas, vous devriez connaître Foo
.
La seule chose que vous puissiez faire est de le transmettre à d'autres méthodes découvertes par réflexion qui acceptent Foo
en tant que paramètre ... Mais la méthode Invoke
accepte un tableau de object
en tant que paramètres ... Vous n'avez pas besoin de convertir votre object
. appeler Invoke
! Il vous suffit de le mettre dans le tableau.
Cela équivaudrait à:
object objFoo = MakeFoo();
Foo result = (Foo)objFoo;
Il est inutile de convertir un objet en un type inconnu au moment de la compilation - vous ne pourrez pas l'utiliser:
object objFoo = MakeFoo();
UnkownType result = (UknownType)objFoo;
Puisque vous ne savez pas ce que UknownType
est, vous ne pourrez utiliser aucune de ses méthodes sans recourir à la réflexion ou à la dynamique.