2010-10-29 11 views
1

Est-il possible d'utiliser Reflection is C# pour déclencher un événement? Dire que j'ai une situation comme celle-ci:C# Créer un délégué qui déclenche un événement?

public delegate void SomeEventHandler(object sender, BenArgs e); 

class EventHub 
{ 
    public event SomeEventHandler SOME_EVENT; 

    public void fireEvent(String eventName) 
    { 
     SomeEventHandler evt = (SomeEventHandler) Delegate.CreateDelegate(typeof(SomeEventHandler), this, eventName); 

     evt.Invoke(null, null); 
    } 
} 

Signification si je l'appelle

EventHub.fireEvent("SOME_EVENT") 

alors il est la plaque tournante événement SOME_EVENT d'incendie? J'ai essayé ceci et je reçois juste des exceptions.

C'est surtout une curiosité de ma part, je sais que dans ce cas je pourrais tout aussi bien tirer l'événement sans réfléchir.

Répondre

3

En supposant que votre scénario actuel, i.e. .:

  1. Un événement comme champ.
  2. Le champ de délégué de support a le même nom que l'événement.
  3. (this, EventArgs.Empty) sont des arguments valides à transmettre au délégué.

Vous pouvez faire quelque chose comme ça (validation plus d'arguments requis):

public void fireEvent(String eventName) 
{ 
    // Get a reference to the backing field 
    var del = (Delegate)typeof(EventHub) 
       .GetField(eventName, BindingFlags.NonPublic | BindingFlags.Instance) 
       .GetValue(this); 

    // Invoke the delegate, it's invocation-list will contain the listeners 
    if(del != null) 
     del.DynamicInvoke(this, EventArgs.Empty); 
} 

Utilisation:

var eHub = new EventHub(); 
    eHub.SOME_EVENT += delegate { Console.WriteLine("SOME_EVENT fired.."); };  
    eHub.fireEvent("SOME_EVENT"); 

Maintenant, vous pouvez généraliser cette idée avec une méthode d'extension sur object si vous comme, mais tout cela est une très mauvaise idée. Ce problème ne peut pas être résolu dans le cas général car on ne peut pas savoir comment un événement est "implémenté". Il pourrait y avoir du code arbitraire dans les méthodeset remove, et la logique pour «déclencher» l'événement pourrait également être à peu près n'importe quoi. Il pourrait même ne pas y avoir un champ de delta de multidiffusion de support pour stocker les auditeurs.

Dans tous les cas, essayer de dire à un objet de déclencher un événement est presque toujours le signe d'un défaut majeur de conception, l'OMI. Si vous encore ne voulez vraiment cela, il serait préférable de déclarer une méthode comme celui-ci dans votre classe:

public void RaiseXXXEvent() { ... } 
+0

Ha! Ça marche! Merci beaucoup. Est-ce que je voudrais utiliser l'invocation dynamique plutôt que Invoke? – Ben

+0

@Ben: À la vôtre. 'System.Delegate' ne déclare pas une méthode' Invoke'. – Ani

+0

Incroyable! Tout à l'heure j'ai essayé avec 'BindingFlags.Instance' seulement parce que je pense que l'événement est' public'. Mais j'obtiens 'FieldInfo [0]'. Pourquoi? –