Beschreibung:
Diese Methode liefert alle Event-Namen & Methoden-Namen an einem Control registrierten EventHandler.
Rückgabewert is ein Dictionary: KEY: Event-Name | VALUE: List<Method-Name>
/// <summary>
/// Search for all event Methods to a given control
/// </summary>
/// <param name="i_control">given control</param>
/// <returns>Dictionary with all events they have a callback method</returns>
public Dictionary<string, List<string>> GetEventMethods(Control i_control)
{
//KEY: Event-Name | VALUE: List<Method-Name>
Dictionary<string, List<string>> eventMethodDic = new Dictionary<string, List<string>>();
EventInfo[] eventInfos = i_control.GetType().GetEvents();
for (int i = 0; i < eventInfos.GetLength(0); i++)
{
string eventName = eventInfos[i].Name;
PropertyInfo propertyInfo = i_control.GetType().GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
object eventHandlerList = propertyInfo.GetValue(i_control, null);
MethodInfo methodInfo = eventHandlerList.GetType().GetMethod("Find", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo fieldInfo = typeof(Control).GetField("Event" + eventName, BindingFlags.Static | BindingFlags.NonPublic);
if (fieldInfo != null)
{
object value = fieldInfo.GetValue(i_control);
object result = methodInfo.Invoke(eventHandlerList, new object[] { value });
if (result != null)
{
object handler = result.GetType().InvokeMember("handler", BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic, null, result, null);
MulticastDelegate md = handler as MulticastDelegate;
Delegate [] delegates = md.GetInvocationList();
List<string> methods = new List<string>();
for (int i2 = 0; i2 < delegates.Length; i2++)
{
if (delegates[i2].Method.Name != null)
methods.Add(delegates[i2].Method.Name);
}
eventMethodDic.Add(eventName, methods);
}
}
}
return eventMethodDic;
}
Aufruf:
Dictionary<string, string> eventDic = this.GetEventMethods(myControl);
Edit:
UPDATE
Schlagwörter: EventHandler, MethodInfo, EventInfo
Hallo,
der Code wird wahrscheinlich nicht in allen Fällen funktionieren. Wenn man nämlich selber ein Control mit eigenen Events definiert, hat man ja die Möglichkeit auch die Eventfelder selbst anzulegen und dann muss die Annahme
FieldInfo fieldInfo = typeof(Control).GetField("Event" + eventName, BindingFlags.Static | BindingFlags.NonPublic);
,dass das Feld mit Event... beginnt, nicht mehr stimmen.
Abgefangen hast du den Fall ja, da du auf null abfragst in nächsten Schritt, aber erwähnen kann mans ja trotzdem 😃
Baka wa shinanakya naoranai.
Mein XING Profil.
Hm, ich hatte da auch mal ne Lösung.
public Dictionary<string, string> GetEventMethods(Control control)
{
Dictionary<string, string> eventMethodDic = new Dictionary<string, string>();
Type controlType = typeof(control);
PropertyInfo events = controlType.GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList value = (EventHandlerList)events.GetValue(control, null);
FieldInfo[] fields = controlType.GetFields(BindingFlags.NonPublic | BindingFlags.Static);
foreach (FieldInfo info in fields)
{
object o = info.GetValue(control);
if (o != null)
{
Delegate eventHandler = value[o];
if (eventHandler != null)
{
eventMethodDic.Add(info.Name, eventHandler.Method.Name);
}
}
}
return eventMethodDic;
}
Kommt aufs Selbe raus....
Hallo,
in Deiner Version steckt in der Zeile:
Type controlType = typeof(control);
ein Fehler.
Es muss heißen:
Type controlType = typeof(Control);
--> GROSSES C --> Typ nicht Object
Edit:
Und desweiteren hängt an Deinen Eventnamen im Dictionary jeweils ein "Event" davor.
Als Beispiel: statt "Click" ein "EventClick". ...aber das nur so erwähnt...
Grüße
ein event ist ein multicastdelegate. das bedeutet, das sich merere methoden anmelden können, die dann der reihe nach aufgerufen werden. deine version wird aber immer nur eine methode zurückgeben.. so wie ich das sehe immer nur die zuletzt registrierte methode.
eigendlich müsstest du ein stringarray oder eine stringlist als value des dictionarys definieren und auch dann ist der methodenname an sich nur wenig informativ, da man ja nciht weiß, wo die methode ist....
edit:
hier hast du noch code zum testen... 😉
static void Main(string[] args)
{
mycontrol b = new mycontrol();
b.test += new EventHandler(b_Click);
b.test += new EventHandler(b_Click2);
Dictionary<string, string> eventDic = GetEventMethods(b);
}
static void b_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
static void b_Click2(object sender, EventArgs e)
{
throw new NotImplementedException();
}
public class mycontrol : Control
{
public event EventHandler test;
}
Hallo JAck30lena,
japp, hast Recht, habs grad getestet.
Werd ich anpassen...
Gutes Auge, Danke für den Hinweis!
Mit deinem Code getestet und für gut befunden:
private static Dictionary<string, List<string>> GetEventMethods(Control control)
{
Dictionary<string, List<string>> eventMethodDic = new Dictionary<string, List<string>>();
Type controlType = control.GetType();
EventInfo[] infos = controlType.GetEvents();
foreach (EventInfo info in infos)
{
FieldInfo fieldInfo = controlType.GetField(info.Name, BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo != null)
{
object o = fieldInfo.GetValue(control);
if (o.GetType() == typeof(EventHandler))
{
EventHandler eventHandler = o as EventHandler;
Delegate[] methods = eventHandler.GetInvocationList();
List<string> methodNames = methods.Select(method => method.Method.Name).ToList();
eventMethodDic.Add(fieldInfo.Name, methodNames);
}
}
}
return eventMethodDic;
}
btw: das klein geschriebene "control" war schon absicht, aber dann gehts natürlich nicht mit "typeof", stattdessen:
Type controlType = control.GetType();
Ein paar Unschönheiten gibt es noch im Code. Siehe Registriere Events auflisten funktioniert bei einem bestimmten Event nicht