Welcome to Usergroups.at Sign in | Join | Faq

Presentation (Windows Forms, Windows Presentation Foundation)

Started by rolandf at 03-27-2006 12:34. Topic has 3 replies.

Print Search
Sort Posts:    
   03-27-2006, 12:34
rolandf is not online. Last active: 08.03.2006 11:20:15 rolandf

Top 25 Posts
Joined on 03-08-2006
Posts 4
Methode die mit EventHandler verbunden ist ermitteln

Attachment: csharp_debug_menuitem_click.jpg

Gibt es eine Möglichkeit zur Laufzeit (mit Reflection) die Methoden festzustellen, die mit dem Click-Event eines Controls verbunden sind (.NET
Framework 1.1)?
Ich möchte nämlich versuchen, zur Laufzet die verbundenen Methoden durch eine ander Methode zu tauschen. Leider habe ich bis jetzt nicht herausfinden können wie ich zu den entsprechenden Informationen gelangen kann. Wenn ich den Code debuge kann ich mir die gesuchte Information ansehen (siehe Anhang: csharp_debug_menuitem_click.jpg, Markierung zeigt die mit dem Click-Event verbundene Methode, Breakpoint bei Methode btnStart_Click).

Ich bin über jede Hilfe dankbar.


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace EventMethods
{
 public class FrmMain : System.Windows.Forms.Form
 {
  private System.ComponentModel.Container components = null;
  private System.Windows.Forms.MenuItem mnuDatei;
  private System.Windows.Forms.MenuItem mnuHilfe;
  private System.Windows.Forms.MenuItem mnuOeffnen;
  private System.Windows.Forms.MenuItem mnuSpeichern;
  private System.Windows.Forms.MenuItem mnuSpeicherUnter;
  private System.Windows.Forms.MainMenu mnuMain;
  private System.Windows.Forms.MenuItem mnuSeparator;
  private System.Windows.Forms.MenuItem mnuUeber;
  private System.Windows.Forms.TextBox txtResult;
  private System.Windows.Forms.Button btnStart;
  private System.Windows.Forms.Button btnBeenden;
  private System.Windows.Forms.MenuItem mnuBeenden;

  public FrmMain()
  {
   InitializeComponent();
  }

  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null)
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  private void mnuBeenden_Click(object sender, System.EventArgs e)
  {
   MessageBox.Show("Beenden");
  }

  private void mnuSpeicherUnter_Click(object sender, System.EventArgs e)
  {
   MessageBox.Show("Speichern unter");
  }

  private void mnuSpeichern_Click(object sender, System.EventArgs e)
  {
   MessageBox.Show("Speichern");

  }

  private void mnuOeffnen_Click(object sender, System.EventArgs e)
  {
   MessageBox.Show("Öffnen");
  }

  private void mnuUeber_Click(object sender, System.EventArgs e)
  {
   MessageBox.Show("Über");
  }

  private void btnStart_Click(object sender, System.EventArgs e)
  {
   // TODO.
  }

  private void btnBeenden_Click(object sender, System.EventArgs e)
  {
   this.Close();
  }

  #region Windows Form Designer generated code

  private void InitializeComponent()
  {
   this.mnuMain = new System.Windows.Forms.MainMenu();
   this.mnuDatei = new System.Windows.Forms.MenuItem();
   this.mnuHilfe = new System.Windows.Forms.MenuItem();
   this.mnuOeffnen = new System.Windows.Forms.MenuItem();
   this.mnuSpeichern = new System.Windows.Forms.MenuItem();
   this.mnuSpeicherUnter = new System.Windows.Forms.MenuItem();
   this.mnuSeparator = new System.Windows.Forms.MenuItem();
   this.mnuBeenden = new System.Windows.Forms.MenuItem();
   this.mnuUeber = new System.Windows.Forms.MenuItem();
   this.txtResult = new System.Windows.Forms.TextBox();
   this.btnStart = new System.Windows.Forms.Button();
   this.btnBeenden = new System.Windows.Forms.Button();
   this.SuspendLayout();
   //
   // mnuMain
   //
   this.mnuMain.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                     this.mnuDatei,
                     this.mnuHilfe});
   //
   // mnuDatei
   //
   this.mnuDatei.Index = 0;
   this.mnuDatei.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                      this.mnuOeffnen,
                      this.mnuSpeichern,
                      this.mnuSpeicherUnter,
                      this.mnuSeparator,
                      this.mnuBeenden});
   this.mnuDatei.Text = "Datei";
   //
   // mnuHilfe
   //
   this.mnuHilfe.Index = 1;
   this.mnuHilfe.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                      this.mnuUeber});
   this.mnuHilfe.Text = "Hilfe";
   //
   // mnuOeffnen
   //
   this.mnuOeffnen.Index = 0;
   this.mnuOeffnen.Text = "Öffnen";
   this.mnuOeffnen.Click += new System.EventHandler(this.mnuOeffnen_Click);
   //
   // mnuSpeichern
   //
   this.mnuSpeichern.Index = 1;
   this.mnuSpeichern.Text = "Speichern";
   this.mnuSpeichern.Click += new
System.EventHandler(this.mnuSpeichern_Click);
   //
   // mnuSpeicherUnter
   //
   this.mnuSpeicherUnter.Index = 2;
   this.mnuSpeicherUnter.Text = "Speichern unter...";
   this.mnuSpeicherUnter.Click += new
System.EventHandler(this.mnuSpeicherUnter_Click);
   //
   // mnuSeparator
   //
   this.mnuSeparator.Index = 3;
   this.mnuSeparator.Text = "-";
   //
   // mnuBeenden
   //
   this.mnuBeenden.Index = 4;
   this.mnuBeenden.Text = "Beenden";
   this.mnuBeenden.Click += new System.EventHandler(this.mnuBeenden_Click);
   //
   // mnuUeber
   //
   this.mnuUeber.Index = 0;
   this.mnuUeber.Text = "Über";
   this.mnuUeber.Click += new System.EventHandler(this.mnuUeber_Click);
   //
   // txtResult
   //
   this.txtResult.Anchor =
((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Bottom)
    | System.Windows.Forms.AnchorStyles.Left)
    | System.Windows.Forms.AnchorStyles.Right)));
   this.txtResult.Location = new System.Drawing.Point(8, 8);
   this.txtResult.Multiline = true;
   this.txtResult.Name = "txtResult";
   this.txtResult.Size = new System.Drawing.Size(276, 203);
   this.txtResult.TabIndex = 0;
   this.txtResult.Text = "";
   //
   // btnStart
   //
   this.btnStart.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Left)));
   this.btnStart.Location = new System.Drawing.Point(8, 219);
   this.btnStart.Name = "btnStart";
   this.btnStart.TabIndex = 1;
   this.btnStart.Text = "Start";
   this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
   //
   // btnBeenden
   //
   this.btnBeenden.Anchor =
((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom
| System.Windows.Forms.AnchorStyles.Right)));
   this.btnBeenden.DialogResult = System.Windows.Forms.DialogResult.Cancel;
   this.btnBeenden.Location = new System.Drawing.Point(212, 219);
   this.btnBeenden.Name = "btnBeenden";
   this.btnBeenden.TabIndex = 2;
   this.btnBeenden.Text = "Beenden";
   this.btnBeenden.Click += new System.EventHandler(this.btnBeenden_Click);
   //
   // FrmMain
   //
   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
   this.CancelButton = this.btnBeenden;
   this.ClientSize = new System.Drawing.Size(292, 251);
   this.Controls.Add(this.btnBeenden);
   this.Controls.Add(this.btnStart);
   this.Controls.Add(this.txtResult);
   this.Menu = this.mnuMain;
   this.MinimumSize = new System.Drawing.Size(300, 300);
   this.Name = "FrmMain";
   this.Text = "Form1";
   this.ResumeLayout(false);

  }
  #endregion

  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main()
  {
   Application.Run(new FrmMain());
  }
 }
}


mfg rolandf

   Report 
   03-29-2006, 14:42
Peter Schneider is not online. Last active: 18.08.2009 13:33:42 Peter Schneider



Top 10 Posts
Joined on 08-19-2005
Posts 46
Re: Methode die mit EventHandler verbunden ist ermitteln

Hallo Roland!

Hmmm.... Das was du erreichen willst, wird so einfach nicht zu lösen sein.

Normalerweise sollte man über

EventInfo eventInfo = button1.GetType().GetEvent("Click");

die auf die einzelnen Informationen zugreifen können... nun ist es aber leider so, dass die EventInfo Klasse
zwar Methoden zur Verfügung stellt um EventHandler zu entfernen und hinzuzufügen, aber leider keine Methode
um die InvocationList aufzurufen.

Mark Levinson hat auf seinem Blog einen kleinen Trick gepostet, hab's selbst aber noch nicht probiert... vielleicht
hilfts dennoch ;-)

http://dotnetjunkies.com/WebLog/mlevison/archive/2004/06.aspx

Dennoch: Ich glaube Reflection ist nicht der richtige Weg um das zu erreichen, was du haben willst. Sollte mit Hilfe
von bestimmten Design Patterns einfacher gehen.

Greetings, Peter Schneider

 


   Report 
   03-31-2006, 0:32
maxhauser is not online. Last active: 09.06.2006 04:33:07 maxhauser

Top 25 Posts
Joined on 10-27-2005
Posts 4
Re: Methode die mit EventHandler verbunden ist ermitteln
Hallo!

Es ist möglich sich von einem Event die angehängten Funktionen rauszuholen. Hab ein bißchen herumprobiert und mit etwas Spucke und viel schmutziger Reflection kommt man über ~5 private Felder zu der gewünschten Info.

Hier ist der Code:

<font face="Lucida Console" size="2">
private MulticastDelegate[] GetEventHandlers(Component component)
{
ArrayList delegateList = new ArrayList();

PropertyInfo eventsProperty = typeof(Component).GetProperty(&quot;Events&quot;, BindingFlags.NonPublic | BindingFlags.Instance);

EventHandlerList list = (EventHandlerList)eventsProperty.GetValue(component, null);

object head = typeof(EventHandlerList).GetField(&quot;head&quot;, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(list);

Type eventHandlerListEntry = head.GetType();

FieldInfo handlerField = eventHandlerListEntry.GetField(&quot;handler&quot;, BindingFlags.NonPublic | BindingFlags.Instance);
delegateList.Add(handlerField.GetValue(head));

FieldInfo nextField = eventHandlerListEntry.GetField(&quot;next&quot;, BindingFlags.NonPublic | BindingFlags.Instance);
object next = nextField.GetValue(head);

while (next != null)
{
delegateList.Add(handlerField.GetValue(next));
next = nextField.GetValue(next);
}

return (MulticastDelegate[])delegateList.ToArray(typeof(MulticastDelegate));
}
</font>

zur Erläuterung: die Component Klasse hat einen protected property namens Events über die man zum Ziel kommt. Dies ist aber ein Spezialfall bei von Component abgeleiteten Klassen (also den UI Klassen wie z.B. Button). Bei "normalen" Klassen ist ein Event als verstecktes Feld in der Klasse eingetragen welches man aber auch über Reflection rausbekommt.

Die zurückgegebenen MulticastDelegate Objekte haben dann auch die gewünschte GetInvocationList() Methode in der alle Funktionen aufgeführt sind.

Ein klitzekleines Problem gibts allerdings noch: Ich habe noch nicht herausgefunden wie man die MulticastDelegates dem eigentlichen Event zuordnen (also z.B. "Click") kann ...

Ehrlicher Weise würd ich diesen Code nicht Verwenden, da bei Verwendung von undokumentierten und noch dazu privaten Membern natürlich immer die Gefahr besteht, daß sies in der nächsten Version nicht mehr gibt. Allerdings veranschaulicht der Code was man alles mit Reflection anstellen kann ;).

Quintessenz: Es geht anscheinend wirklich nicht auf "normalem" Wege und ich halte Peters Tipp an dem Design zu drehen im Endeffekt auch am besten.

Gruß,

Max
   Report 
   04-03-2006, 7:08
rolandf is not online. Last active: 08.03.2006 11:20:15 rolandf

Top 25 Posts
Joined on 03-08-2006
Posts 4
Re: Methode die mit EventHandler verbunden ist ermitteln
Hallo!

Danke für eure Hilfe.
Die Tips haben mir sehr geholfen.

mfg Roland

   Report 
Usergroups.at » Core Technologi... » Presentation (W... » Re: Methode die mit EventHandler verbunden ist ermitteln

Powered by Community Server, by Telligent Systems