Scope when using Event Handlers and Reflection
I have a Button
defined in Xaml like
<Button Name="button1" />
I'm trying to subscribe to the Click
event of this Button
using Reflection. More precisely I want to invoke an Action<object, EventArgs>
and inside the event handler I want to access a local variable from outside of the scope like this
s开发者_JAVA技巧tring testString = "Hello";
Action<object, EventArgs> clickAction = (object sender, EventArgs e) =>
{
MessageBox.Show(testString);
};
If I do this, Hello
is displayed
clickAction.Invoke(null, null);
Similar, if I just subscribe to the Click
event like this, Hello
is displayed
button1.Click += (sender, e) =>
{
MessageBox.Show(testString);
};
But if I use reflection to subscribe to the event with AddEventHandler
, I'm unable to access testString
and I get a NullReferenceException
in the event handler.
Type buttonType = button1.GetType();
EventInfo clickEvent = buttonType.GetEvent("Click");
Delegate clickEventHandler = Delegate.CreateDelegate(clickEvent.EventHandlerType,
null,
clickAction.Method);
clickEvent.AddEventHandler(button1, clickEventHandler);
- Why does this happend?
- Is there a fix I can apply to make it work the way I want?
- Do I have another option?
Update - This is what the Method looks like in full
private void MyMethod()
{
string testString = "Hello";
Action<object, EventArgs> clickAction = (object sender, EventArgs e) =>
{
MessageBox.Show(testString);
};
Type buttonType = button1.GetType();
EventInfo clickEvent = buttonType.GetEvent("Click");
Delegate clickEventHandler = Delegate.CreateDelegate(clickEvent.EventHandlerType,
null,
clickAction.Method);
clickEvent.AddEventHandler(button1, clickEventHandler);
}
EDIT - rewriting my answer after the comments:
you can make this work if you bind the delegate to an instance. that instance should be a class containing all information/variable you want to use from within your event handler... you create that instance, initialize it with the values you want and then bind it:
Delegate clickEventHandler = Delegate.CreateDelegate(clickEvent.EventHandlerType, yourinstance, clickAction.Method);
this way the delegate has a "this" which can be used to access the variables...
you could even make those variables instead of local just plain class fields and bind the delegate to this
.
another option would be to put thos variables into the "sender object" and access them that way...
精彩评论