2017-07-26 6 views
3

Tenir compte cet exemple de code à partir d'une application WinForms:Pourquoi la méthode Invoke échoue-t-elle avec l'argument argument?

public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      object[] parms = new object[1]; 
      parms[0] = "foo"; 

      DoSomething(parms); 
     } 

     public static string DoSomething(object[] parms) 
     { 
      Console.WriteLine("Something good happened"); 
      return null; 
     } 
    } 

Il fonctionne comme prévu, lorsque vous cliquez sur button1 il imprime « Quelque chose est arrivé » à la console.

considèrent maintenant cet exemple de code, qui est le même, sauf qu'il invoque DoSomething utilisant la réflexion:

public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      object[] parms = new object[1]; 
      parms[0] = "foo"; 

      System.Reflection.MethodInfo mi = typeof(Form1).GetMethod("DoSomething"); 
      mi.Invoke(null, parms); 

     } 

     public static string DoSomething(object[] parms) 
     { 
      Console.WriteLine("Something good happened"); 
      return null; 
     } 
    } 

Il jette un System.ArgumentException sur la ligne mi.Invoke(null, parms) (objet de type « System.String » ne peut pas être converti en tapez 'System.Object []'.)

Parms est clairement un tableau d'objets, et la signature de la méthode DoSomething attend clairement un tableau d'objets. Alors pourquoi invoquer tire-t-il le premier objet hors du tableau et essaye-t-il de le passer à la place?

Ou est quelque chose d'autre que je ne comprends pas?

Répondre

7

MethodInfo.Invoke attend un tableau d'objets, où chaque objet du tableau d'objet correspond à un argument à la méthode. Le premier argument dans le tableau d'objets est le premier argument, le deuxième objet dans le tableau la deuxième méthode, etc.

Puisque vous voulez que le premier argument de votre méthode soit object[], vous devez vous assurer que le premier objet dans le tableau d'objets que vous passez à MethodInfo.Invokeest un tableau d'objets qui représente le tableau que DoSomething doit utiliser.

+1

Cela est logique parfait maintenant - bien sûr, il fonctionne de cette façon. Il est temps de s'éloigner du clavier pendant quelques minutes :-) – GojiraDeMonstah

2
object[] parms = new object[1]; 
parms[0] = "foo"; 

avec:

public static string DoSomething(object[] parms) 

qui est le problème; le premier paramètre n'est pas string - il s'agit d'un object[]. Le object[] que vous passez à Invoke représente chaque paramètre tour à tour, de sorte qu'un object[] de longueur 1 avec une chaîne correspond à static string DoSomething(string s), mais ne correspond pas à votre méthode. Modifiez la signature ou enveloppez la valeur. Franchement, je vous suggérons de changer la signature est la meilleure idée, mais:

parms[0] = new object[] { "foo" }; 

travaillerait aussi

1

MethodInfo.InvokeMethodInfo.Invoke s'attend à ce qu'un tableau d'objets en tant que paramètre transmette plusieurs arguments aux fonctions, chaque objet dans le tableau sera un paramètre différent.

Comme votre fonction attend également un tableau d'objets vous passez en argument non pas un tableau d'objets mais une chaîne.

Vous devez placer ce tableau dans un autre tableau. De cette manière, l'appel lancera le premier tableau et utilisera le tableau interne comme premier paramètre de l'appel.

mi.Invoke(null, new object[]{ parms }); 
1

parms is clearly an object array, and DoSomething's method signature is clearly expecting an object array.

Oui, il attend un tableau d'objets.Mais quand vous passez ceci:

object[] parms = new object[1]; 

Vous dites que ce sont les arguments pour DoSomething si parms [0] est le premier argument de DoSomething et s'il y avait plus d'articles dans parms puis parms [1] sera le 2ème argument et ainsi de suite.

Il est clair que le premier argument pour DoSomething n'est pas un string (parms [0]) afin que vous obtenez cette erreur:

It throws an System.ArgumentException on the line mi.Invoke(null, parms) (Object of type 'System.String' cannot be converted to type 'System.Object[]'.)