Here is my problem/scenario
public class TestEventArgs : EventArgs
{
public int ID { get; set; }
public string Name { get; set; }
}
public event EventHandler<TestEventArgs> TestClick
How can I attach an EventHandler on TestClick by using reflection? (obj is instance, Activator.CreateInstance)
EventInfo eventClick = obj.GetType().GetEvent("TestClick");
Delegate handler = Delegate.CreateDelegate(eventClick.EventHandlerType, obj, ????);
eventClick.AddEventHandler(obj, handler);
My problem being that TestEventArgs is declared in an external dll, but ???? methodinfo above requires the signature in its delegate?
I manage to get my code to work by following the technique describe by the following article,
http://www.pelennorfields.com/matt/2009/03/13/createdelegate-error-binding-to-target-method/
In essence, if I do the following, I get the error, "Error binding to target method",
FAIL:
EventInfo eventClick = obj.GetType().GetEvent("TestClick");
Delegate handler = Delegate.CreateDelegate(
eventClick.EventHandlerType, this, "TestClick");
eventClick.AddEventHandler(obj, handler);
SUCCESS:
But when I changed it to:
MethodInfo methodOn_TestClick = this.GetType().GetMethod("TestClick", new Type[] { typeof(object), typeof(EventArgs));
Delegate handler = Delegate.CreateDelegate(
event_DomClick.EventHandlerType, this, methodOn_TestClick, true); // note the change here
eventClick.AddEventHandler(obj, handler);
I then used reflection in my TestClick method, to get the properties I needed out of the standard EventArgs.
eg.
public void TestClick(object sender, EventArgs e)
{
PropertyInfo prop_ID = e.GetType().GetProperty("ID");
int id = Convert.toInt32(prop_ID.GetValue(e, null));
}
Do you control the source of the target assembly? If so, simply add the InternalsVisibleTo assembly attribute to the target assembly.
If you used Activator.CreateInstance()
you've got a reference to the type of your object right?
To add your own handler:
Call type.GetFields()
on it, now you've got the internal fields (if the event is defined in a base class you need to first walk up the heirachy using type.BaseType
to go up a level to you get to the level you need).
Once you have a FieldInfo
instance for the delegate backing the event handler call GetValue()
on the FieldInfo
instance passing your object in. Now you've got the delegate backing the event handler. Now call FieldInfo.SetValue(myObject, Delegate.Combine(currentValue, myHandler))
.
I'm pretty sure that with Delegate.Combine you just have to make sure the signature of your event handler matches, but not the actual type. So it should be enough to create your own delegate with the same signature.