问题
I am trying to use Reflection to add a method from a class to an event. Here is my setup.
- Have a class with a keyPressDown & keyPressUp method. I also have an Event in this class. keyPressDown & keyPressUp will fire whatever methods are subscribed to it (if any).
These additional methods are controlling RGB light emitting diodes. One method can flash a color, another can fade a color, etc..
I can subscribe to the event like myEventKeyUp += myClass.MethodA;
My problem is, I am storing the configuration the user wants in a database. So the only thing I can think of is storing the Method Name as text and use reflection to add it to the event handler.
Code Example:
Class MyClass
public event delegateKeyDown keyDownEvent;
public event delegateKeyUp keyUpEvent;
public void KeyUp()
{
joystick.SetBtn(false, 1, vJoyButtonID);
if (keyUpEvent != null) keyUpEvent();
}
public void KeyDown()
{
joystick.SetBtn(true, 1, vJoyButtonID);
// IF WE HAVE ANY LISTENERS THEN FIRE THEM
if (keyDownEvent != null) keyDownEvent();
}
public void MethodA()
{
// DO SOMeTHING HERE
}
Main Form
button.keyDownEvent += button.SetRandomColor;
button.keyUpEvent += button.TurnOff;
What I need to do is something like: button.keyUpEvent += MyClass.GetType().GetMethod("MethodA");
I know you can't do what I am trying to do with Reflection, I read that I can use reflection to get hold of the delegate that contains the event handler, and add it through that way but I am unsure (or unclear about this).
回答1:
In the vein of Jim W's link, here's a working example:
using System;
using System.Reflection;
internal class Program
{
private static void Main()
{
var foo = new Foo();
var fooType = foo.GetType();
var eventInfo = fooType.GetEvent("Bar");
var methodInfo = fooType.GetMethod("OnBar", BindingFlags.Static | BindingFlags.Public);
eventInfo.AddEventHandler(foo, Delegate.CreateDelegate(eventInfo.EventHandlerType, methodInfo));
foo.RaiseBar();
Console.ReadKey();
}
}
public class Foo
{
public delegate void BarHandler(object sender, BarEventArgs args);
public event BarHandler Bar;
public void RaiseBar()
{
Bar(this, new BarEventArgs());
}
public static void OnBar(object sender, BarEventArgs args)
{
Console.WriteLine(args.Guid);
}
}
public class BarEventArgs : EventArgs
{
public Guid Guid => Guid.NewGuid();
}
回答2:
Thanks for both of your help. Between the two examples shown I was able to wrap my head around this. I Made a function to handle the event setup as follows:
private void SetupEventHandlers(RGBButton button,string EventName, string MethodName)
{
// THIS SETS UP THE EVENT HANDLER THAT WILL FIRE ANY ADDITION
// ACTIONS THE USER COULD WANT WHEN A BUTTON IS PRESSED OR RELEASED.
var p = button;
var eventInfo = p.GetType().GetEvent(EventName);
var methodInfo = typeof(RGBButton).GetMethod(MethodName);
try
{
// TRY TO SUBSCRIBE TO OUR KEYUP OR KEYDOWN EVENT
Delegate handler = Delegate.CreateDelegate(eventInfo.EventHandlerType, p, methodInfo);
eventInfo.AddEventHandler(p, handler);
}
catch (Exception)
{
// MOST LIKELY COULDN'T FIND THE METHOD WE ARE TRYING TO FIRE
throw new System.InvalidOperationException("Failed to find method: " + MethodName + "', which is registered as an Event Subscriber.");
}
}
This allows me to add to an event in my class (a few different events) with any given name (stored in a database) all from one function. the var P = button is a class which defines my RGB Led arcade buttons. That class contains the events that get triggered when the button is pressed.
来源:https://stackoverflow.com/questions/49290793/c-sharp-adding-a-listener-to-event-with-only-the-method-name-text