Wie ein Feld durch Reflexion referenzieren
-
30-09-2019 - |
Frage
Sorry für den Titel, es ist nicht explizit.
Weitere meines Präzedenzfall Frage , ich will eine Methode auf ein Ereignis-Objekt zeichnen dynamisch abgerufen (durch Reflexion). Das betreffende Objekt ist ein Feld einer Steuerung:
public void SubscribeEvents(Control control)
{
Type controlType = control.GetType();
FieldInfo[] fields = controlType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo method = typeof(Trace).GetMethod("WriteTrace");
// "button1" hardcoded for the sample
FieldInfo f = controlType.GetField("button1", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
// "Click" hardcoded for the sample
EventInfo eInfo = f.FieldType.GetEvent("Click");
if (eInfo != null)
{
EventHandler dummyDelegate = (s, e) => WriteTrace(s, e, eInfo.Name);
Delegate realDelegate = Delegate.CreateDelegate(eInfo.EventHandlerType, dummyDelegate.Target, dummyDelegate.Method);
eInfo.AddEventHandler(?????, realDelegate); // How can I reference the variable button1 ???
}
}
Ich weiß nicht, wie die Variable verweisen ‚button1‘. Ich habe so etwas wie dies versucht:
public void SubscribeEvents(Control control)
{
Type controlType = control.GetType();
FieldInfo[] fields = controlType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo method = typeof(Trace).GetMethod("WriteTrace");
// "button1" hardcoded for the sample
FieldInfo f = controlType.GetField("button1", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
// "Click" hardcoded for the sample
EventInfo eInfo = f.FieldType.GetEvent("Click");
Type t = f.FieldType;
object o = Activator.CreateInstance(t);
f.GetValue(o);
if (eInfo != null)
{
EventHandler dummyDelegate = (s, e) => WriteTrace(s, e, eInfo.Name);
Delegate realDelegate = Delegate.CreateDelegate(eInfo.EventHandlerType, dummyDelegate.Target, dummyDelegate.Method);
eInfo.AddEventHandler(o, realDelegate); // Why can I refer to the variable button1 ???
}
}
Aber ich habe hier eine Ausnahme:
f.GetValue(o);
System.ArgumentException wurde nicht behandelt Message = Feld ‚button1‘ definiert auf Typ ‚WindowsFormsApplication1.Form1‘ ist kein Feld auf dem Zielobjekt, das vom Typ ‚System.Windows.Forms.Button‘.
Lösung
Das ist, weil Sie versuchen, eine neue Instanz von Button
zu erstellen und zu versuchen, den Wert seiner button1
Eigenschaft zu erhalten, die offensichtlich nicht existiert.
Ersetzen Sie diese:
Type t = f.FieldType;
object o = Activator.CreateInstance(t);
f.GetValue(o);
mit dieser:
object o = f.GetValue(control);
Sie können eine Methode wie diese verwenden Sie den Wert eines Feldes für jedes Objekt zu erhalten:
public static T GetFieldValue<T>(object obj, string fieldName)
{
if (obj == null)
throw new ArgumentNullException("obj");
var field = obj.GetType().GetField(fieldName, BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
if (field == null)
throw new ArgumentException("fieldName", "No such field was found.");
if (!typeof(T).IsAssignableFrom(field.FieldType))
throw new InvalidOperationException("Field type and requested type are not compatible.");
return (T)field.GetValue(obj);
}