2010-09-23 14 views
7

Mevcut dersten tüm olayları almam ve ona abone olan yöntemleri bulmam gerekiyor. Here I got some answers on how to do that, ama tüm sahip olduğum zaman EventInfodelegate nasıl alabilirim bilmiyorum.Bir EventInfo'dan temsilci nesnesi nasıl alınır?

var events = GetType().GetEvents(); 

foreach (var e in events) 
{ 
    Delegate d = e./*GetDelegateFromThisEventInfo()*/; 
    var methods = d.GetInvocationList(); 
} 

o EventInfo bir temsilci almak mümkün mü? Nasıl?

+1

önceki soru üzerine en yüksek oyu cevap alıntı: "Şimdi diyelim ki bu olabilir cesedini bulmaya 'add' işleyici koda ve olay işleyicileri olmak nasıl iş dışarı saklanır ve onları bu şekilde alırsınız ... ** ama lütfen yapma ** Çok kapsayıcılığı kırmak için çok fazla iş yaratıyorsunuz sadece kodunuzu yeniden tasarlamak ** Bunu yap." Bütün kalbimle katılıyorum. –

cevap

12

var events = GetType().GetEvents(); ifadesi geçerli türle ilişkilendirilmiş EventInfo nesnelerinin listesini sunar; geçerli örnek başına değil. Bu nedenle, EventInfo nesnesi, geçerli örnekle ilgili bilgi içermez ve dolayısıyla kablolu delege hakkında bilgi sahibi olmaz.

İstediğiniz bilgileri almak için, geçerli örneğinizdeki olay işleyicisinin destek alanını almanız gerekir. Yani şimdi çağıran kod şöyle olabilir

public class MyClass 
{ 
    public event EventHandler MyEvent; 

    public IEnumerable<MethodInfo> GetSubscribedMethods() 
    { 
     Func<EventInfo, FieldInfo> ei2fi = 
      ei => this.GetType().GetField(ei.Name, 
       BindingFlags.NonPublic | 
       BindingFlags.Instance | 
       BindingFlags.GetField); 

     return from eventInfo in this.GetType().GetEvents() 
       let eventFieldInfo = ei2fi(eventInfo) 
       let eventFieldValue = 
        (System.Delegate)eventFieldInfo.GetValue(this) 
       from subscribedDelegate in eventFieldValue.GetInvocationList() 
       select subscribedDelegate.Method; 
    } 
} 

: İşte nasıl

class GetSubscribedMethodsExample 
{ 
    public static void Execute() 
    { 
     var instance = new MyClass(); 
     instance.MyEvent += new EventHandler(MyHandler); 
     instance.MyEvent += (s, e) => { }; 

     instance.GetSubscribedMethods() 
      .Run(h => Console.WriteLine(h.Name)); 
    } 

    static void MyHandler(object sender, EventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 
} 

yukarıdaki çıktısı şu şekildedir:

MyHandler 
<Execute>b__0 

Sana etrafında jig eminim Eğer metod bilgisinden ziyade delege geri dönmek isterseniz, bu kod size yardımcı olacaktır.

Umarım bu yardımcı olur.

Benzer
+0

Bu gerçekten şifreli, ben bile okuyamıyorum. – jcmcbeth

+0

@jcmcbeth - Hangi bölüm şifreli? – Enigmativity

+1

EventInfo - FieldInfo temsilcisiniz (ei2fi), [özel eklenti ekleyip kaldırılan olaylar] için çalışmamaktadır (http://msdn.microsoft.com/en-us/magazine/cc163533.aspx). –

2

Enigmativityiçin, çağırma liste ... diğer sınıfların değil, sadece geçerli sınıf için

private void testit() 
    { 
     WithEvents we = new WithEvents(); 
     we.myEvent += new EventHandler(we_myEvent); 
     we.myEvent += new EventHandler(we_myEvent2); 

     foreach (EventInfo ev in we.GetType().GetEvents()) 
     { 
      FieldInfo fi = we.GetType().GetField(ev.Name, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy); 
      Delegate del = (Delegate)fi.GetValue(we); 
      var list = del.GetInvocationList(); 
      foreach (var d in list) 
      { 
       Console.WriteLine("{0}", d.Method.Name); 
      } 
     } 
    } 

    void we_myEvent(object sender, EventArgs e) 
    { 
    } 
    void we_myEvent2(object sender, EventArgs e) 
    { 
    } 


public class WithEvents 
{ 
    public event EventHandler myEvent; 
} 

... bulunabilir sürece olay işleyicileri sınıf olarak da bildirim yapılmış yukarıda görüyoruz. Ancak, EventHandlerList öğesinin "Olaylar" özelliğinde depolandığı Denetim sınıfını düşünün ve her olay alanı adı "Olay" ile ve ardından etkinlik adıyla başlar. Daha sonra, olayları daha farklı bir şekilde yöneten Form türetilmiş sınıflar var. Düşünce için yiyecek.

2

Benim durumum için, alan değeri (sınıf ToolStripMenuItem, alan EventClick), temsilci değil, tip nesnesine aittir. Les'in cevabında, here'dan aldığım şekilde anlattığı Events mülküne başvurmak zorunda kaldım. Bu durumda EventClick alanı sadece bu özellikte depolanan EventHandlerList anahtarını tutar.

Diğer bazı açıklamalar:

  • Ben her durumda işe yaramaz istihdam kuralı fieldName = "Event" + eventName. Maalesef, etkinlik adının alan adına bağlanması için ortak bir kural yoktur. Eşleme için this article benzeri bir statik sözlük kullanmayı deneyebilirsiniz.
  • BindingFlags hakkında hiçbir zaman emin değilim. Başka bir senaryoda, bunları değiştirmeniz gerekebilir.

    /// <summary> 
    /// Gets the EventHandler delegate attached to the specified event and object 
    /// </summary> 
    /// <param name="obj">object that contains the event</param> 
    /// <param name="eventName">name of the event, e.g. "Click"</param> 
    public static Delegate GetEventHandler(object obj, string eventName) 
    { 
        Delegate retDelegate = null; 
        FieldInfo fi = obj.GetType().GetField("Event" + eventName, 
                  BindingFlags.NonPublic | 
                  BindingFlags.Static | 
                  BindingFlags.Instance | 
                  BindingFlags.FlattenHierarchy | 
                  BindingFlags.IgnoreCase); 
        if (fi != null) 
        { 
         object value = fi.GetValue(obj); 
         if (value is Delegate) 
          retDelegate = (Delegate)value; 
         else if (value != null) // value may be just object 
         { 
          PropertyInfo pi = obj.GetType().GetProperty("Events", 
                  BindingFlags.NonPublic | 
                  BindingFlags.Instance); 
          if (pi != null) 
          { 
           EventHandlerList eventHandlers = pi.GetValue(obj) as EventHandlerList; 
           if (eventHandlers != null) 
           { 
            retDelegate = eventHandlers[value]; 
           } 
          } 
         } 
        } 
        return retDelegate; 
    } 
    
+0

dan almanız gerekiyor. Teşekkürler! – Law

İlgili konular