开发者

C# Reflection Programmatic Event Handlers with Custom Event Args

Here is my problem/scenario

public class TestEventArgs : EventArgs
{
   public int ID { get; set; }
   public string Name { get; set; }
}

public event EventHandler<TestEventArgs> Tes开发者_运维知识库tClick

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜