2011-04-20 4 views
4

Mon code est le suivant:erreur de délégué en C#

class PropertyRetrievalClass 
{ 
    public delegate object getProperty(string input); 

    public object get_Chart_1(string iput) 
    { 
     Console.WriteLine(iput); 
     return ""; 
    } 
    public object get_Chart_2(string iput) 
    { 
     Console.WriteLine(iput); 
     return ""; 
    } 

    public PropertyRetrievalClass() { } 
} 

public static void Main() 
     { 
      int i = 1; 
      PropertyRetrievalClass obj = new PropertyRetrievalClass(); 

      Delegate del = Delegate.CreateDelegate(typeof(PropertyRetrievalClass), obj, "get_chart_" + i.ToString()); 
      string output= del("asldkl"); 
     } 

Il me donne une erreur « erreur CS0118: « del » est une « variable » mais est utilisé comme une« méthode »

Que dois-je faire pour utiliser ce délégué? Je veux appeler l'une des fonctions "get_chart_1" ou "get_chart_2" et les deux prennent une entrée de chaîne?

Merci à l'avance ...

Répondre

3

Vous avez deux problèmes dans votre code.

  • Un objet Delegate est pas une méthode, vous devez donc utiliser une méthode sur l'objet Delegate d'invoquer la méthode, il se réfère
  • Le premier argument de CreateDelegate devrait être le type de délégué, et non la classe contenant une méthode que vous souhaitez appeler.

exemple de travail complet:

public delegate void ParamLess(); 
class SomeClass 
{ 
    public void PrintStuff() 
    { 
     Console.WriteLine("stuff"); 
    } 
} 
internal class Program 
{ 
    private static Dictionary<int, int> dict = null; 
    static void Main() 
    { 
     var obj = new SomeClass(); 
     Delegate del = Delegate.CreateDelegate(typeof(ParamLess), obj, 
       "PrintStuff", false); 
     del.DynamicInvoke(); // invokes SomeClass.PrintStuff, which prints "stuff" 
    } 
} 

Dans votre cas, la méthode Main devrait ressembler à ceci:

public static void Main() 
{ 
    int i = 1; 
    PropertyRetrievalClass obj = new PropertyRetrievalClass(); 

    Delegate del = Delegate.CreateDelegate(
     typeof(PropertyRetrievalClass.getProperty), 
     obj, 
     "get_Chart_" + i.ToString()); 
    string output = (string)del.DynamicInvoke("asldkl"); 
} 

Mise à jour
Notez que CreateDelegate est sensible à la casse sur la méthode nom, sauf si vous lui dites de ne pas le faire.

// this call will fail, get_chart should be get_Chart 
Delegate del = Delegate.CreateDelegate(
     typeof(PropertyRetrievalClass.getProperty), 
     obj, 
     "get_chart_" + i.ToString()); 


// this call will succeed 
Delegate del = Delegate.CreateDelegate(
     typeof(PropertyRetrievalClass.getProperty), 
     obj, 
     "get_Chart_" + i.ToString()); 


// this call will succeed, since we tell CreateDelegate to ignore case 
Delegate del = Delegate.CreateDelegate(
     typeof(PropertyRetrievalClass.getProperty), 
     obj, 
     "get_chart_" + i.ToString(), 
     true); 
+0

Vous avez une exception: Erreur de liaison à la méthode cible :-( – seoul

+0

@seoul: voir mise à jour dans la réponse –

+0

Détail et réponse utile :-) Merci ... – seoul

0

Vous ne pouvez pas appeler une méthode sur Delegatede type. Vous devez utiliser DynamicInvoke() qui est très lentewwww.

Essayez ceci:

string output = (string) del.DynamicInvoke(new object[]{"asldkl"}); 
0

Vous utilisez la classe Delegate pas le mot-clé delegate.

0

Vous pouvez uniquement appeler des délégués avec une syntaxe d'appel de méthode, s'ils ont une signature connue. Vous devez convertir votre délégué au type de délégué que vous avez défini précédemment.

var del = (PropertyRetrievalClass.getProperty)Delegate.CreateDelegate(typeof(PropertyRetrievalClass.getProperty), obj, "get_Chart_" + i.ToString()); 

Vous devez également modifier le premier argument de CreateDelegate, car il devrait être le type de délégué. Et capitaliser le "C" dans "get_Chart_".

Et puis, vous aurez besoin de jeter le retour object-string:

string output= (string) del("asldkl"); 

Ou changer le type de délégué et les méthodes d'avoir string leur type de retour.

+1

getProperty n'est pas visible par Main. Ainsi édité de cette façon-> PropertyRetrievalClass.getProperty del = (PropriétéRetrievalClass.getProperty) Delegate.CreateDelegate (typeof (PropertyRetrievalClass), obj, "get_chart_" + i.ToString()); sortie de chaîne = new del ("asldkl"); ************** Cela ne fonctionne pas non plus ... J'ai eu cette erreur-> Le type ou le nom d'espace de noms 'del' est introuvable (il vous manque un en utilisant une directive ou une référence d'assembly?) – seoul

1

Les autres réponses ont résolu le problème avec votre code, mais je voulais offrir une alternative.

S'il y a un nombre limité, fini de méthodes que votre classe de recherche est le choix de, et ils ont les mêmes signatures, cela peut être fait beaucoup plus efficace sans utiliser la réflexion:

public int MethodIndex {get;set;} 
public static void Main() 
{ 
    PropertyRetrievalClass obj = new PropertyRetrievalClass(); 
    Func<string,object> getChartMethod; 
    switch(MethodIndex) 
    { 
     case 1: 
      getChartMethod = obj.get_chart_1; 
      break; 
     case 2: 
      getChartMethod = obj.get_chart_2; 
      break; 
    }    
    string output= getChartMethod("asldkl"); 
} 

S'il y avait beaucoup, vous pourriez simplement créer un tableau au lieu d'utiliser un commutateur. Évidemment, vous pouvez simplement exécuter la fonction appropriée directement à partir du commutateur, mais je suppose que l'idée est que vous souhaitiez renvoyer le délégué à l'appelant, et une construction comme celle-ci vous permet de le faire sans utiliser de réflexion, par ex.

public static Func<string,object> GetMethod 
{ 
... just return getChartMethod directly 
} 
+0

yah ... peut-être une solution aussi si je ne suis pas obligé d'utiliser un délégué seulement. – seoul

+0

+1 aussi pour votre idée. – seoul