|
|
Presentation (Windows Forms, Windows Presentation Foundation)
Started by rolandf at 03-27-2006 12:34. Topic has 3 replies.
 
 
|
|
Sort Posts:
|
|
|
|
03-27-2006, 12:34
|
rolandf
Joined on 03-08-2006
Posts 4
|
|
|
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

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
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("Events", BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)eventsProperty.GetValue(component, null);
object head = typeof(EventHandlerList).GetField("head", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(list);
Type eventHandlerListEntry = head.GetType();
FieldInfo handlerField = eventHandlerListEntry.GetField("handler", BindingFlags.NonPublic | BindingFlags.Instance);
delegateList.Add(handlerField.GetValue(head));
FieldInfo nextField = eventHandlerListEntry.GetField("next", 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
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
|
|
|
|