473,503 Members | 1,979 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Using reflection to unsubscribe an event

I have a library I'm using that has a lapsed listener issue. I figured I'd
just sneak in and do the unsubscription myself since I don't expect it to be
fixed any time soon.

So, I have the control whose event its subscribed to and it's subscribed to
the VisibleChanged event and has an event handler called
ControlVisibleChanged.

So basically, what I want to do is:

myControl.VisibleChanged -= new
EventHandler(myControl.ControlVisibleChanged);

The problem is myControl.ControlVisibleChanged is private.

So, what do I pass to the EventHandler constructor?

Thanks
Aug 30 '07 #1
10 4353
>The problem is myControl.ControlVisibleChanged is private.
>
So, what do I pass to the EventHandler constructor?
If you hav the right permissions you can get a MethodInfo for a
private method with Reflection as well. Just make sure you include
BindingFlags.NonPublic when retrieving it.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Aug 31 '07 #2
"Mattias Sjögren" <ma********************@mvps.orgwrote in message
news:%2****************@TK2MSFTNGP02.phx.gbl...
The problem is myControl.ControlVisibleChanged is private.

So, what do I pass to the EventHandler constructor?

If you hav the right permissions you can get a MethodInfo for a
private method with Reflection as well. Just make sure you include
BindingFlags.NonPublic when retrieving it.
Mattias
I can get the MethodInfo, but I can't pass the MethodInfo to new
EventHandler() because it doesn't take a method info. It normally takes the
method itself and I certainly need to pass the class instance associated
with the method, somehow.

Aug 31 '07 #3
On Aug 31, 1:33 pm, "pedrito" <pixbypedrito at yahoo.comwrote:
I can get the MethodInfo, but I can't pass the MethodInfo to new
EventHandler() because it doesn't take a method info. It normally takes the
method itself and I certainly need to pass the class instance associated
with the method, somehow.
Is Delegate.CreateDelegate what you're after?

Jon

Aug 31 '07 #4

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:11**********************@r29g2000hsg.googlegr oups.com...
On Aug 31, 1:33 pm, "pedrito" <pixbypedrito at yahoo.comwrote:
>I can get the MethodInfo, but I can't pass the MethodInfo to new
EventHandler() because it doesn't take a method info. It normally takes
the
method itself and I certainly need to pass the class instance associated
with the method, somehow.

Is Delegate.CreateDelegate what you're after?

Jon
Jon,

That may just do it. Thanks. I've never actually tried this before, so we'll
see how it goes. Thanks.

Pete
Aug 31 '07 #5
"pedrito" <pixbypedrito at yahoo.comwrote in message
news:ir******************************@giganews.com ...
>
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:11**********************@r29g2000hsg.googlegr oups.com...
>On Aug 31, 1:33 pm, "pedrito" <pixbypedrito at yahoo.comwrote:
>>I can get the MethodInfo, but I can't pass the MethodInfo to new
EventHandler() because it doesn't take a method info. It normally takes
the
method itself and I certainly need to pass the class instance associated
with the method, somehow.

Is Delegate.CreateDelegate what you're after?

Jon

Jon,

That may just do it. Thanks. I've never actually tried this before, so
we'll see how it goes. Thanks.

Pete
Jon,

Not having any luck. This is what I did:

parentControl.VisibleChanged -=
Delegate.CreateDelegate(typeof(EventHandler), myControl,
"ControlVisibleChanged") as EventHandler;

ControlVisibleChanged is the event handler. myControl is the control that
subscribed to parentControl.VisibleChanged.

When I do this, I get an ArgumentException with the message, "Error binding
to target method", which I can only assume is ControlVisibleChanged because
it's private.

I'm using .NET 1.1, so I don't get the overrides of CreateDelegate that take
a MethodInfo and an object instance, not that it looks like it would matter.
It appears that the exception being thrown is coming from an internal
implementation given that the callstack is:

System.ArgumentException: Error binding to target method.
at System.Delegate.InternalCreate(Object target, String method, Boolean
ignoreCase)
at System.Delegate.CreateDelegate(Type type, Object target, String
method)

and

[MethodImpl(MethodImplOptions.InternalCall)]
internal extern void InternalCreate(object target, string method, bool
ignoreCase);

Any idea on how I might around this?

Aug 31 '07 #6
On Aug 31, 2:31 pm, "pedrito" <pixbypedrito at yahoo.comwrote:

<snip>
I'm using .NET 1.1, so I don't get the overrides of CreateDelegate that take
a MethodInfo and an object instance, not that it looks like it would matter.
No, I think that's absolutely what matters. I don't see any reason why
it shouldn't work if you can create the delegate. Unfortunately,
without the right overloads, I'm not sure of the best way of doing
this.

What you *could* do is create a class to encapsulate the method info
and target, and expose a method which has the appropriate signature to
be used as an event handler - that could then call MethodInfo.Invoke.
It would be relatively slow, but it should work.

Jon

Aug 31 '07 #7

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:11**********************@r34g2000hsd.googlegr oups.com...
On Aug 31, 2:31 pm, "pedrito" <pixbypedrito at yahoo.comwrote:

<snip>
>I'm using .NET 1.1, so I don't get the overrides of CreateDelegate that
take
a MethodInfo and an object instance, not that it looks like it would
matter.

No, I think that's absolutely what matters. I don't see any reason why
it shouldn't work if you can create the delegate. Unfortunately,
without the right overloads, I'm not sure of the best way of doing
this.

What you *could* do is create a class to encapsulate the method info
and target, and expose a method which has the appropriate signature to
be used as an event handler - that could then call MethodInfo.Invoke.
It would be relatively slow, but it should work.

Jon
Jon,

You're right. The "Not that it matters" was wrong because the problem is
that it's looking for a public reference.

Here's what I did and I should probably be thrown in jail for doing this,
but it almost seems to have worked.

MethodInfo ovc = typeof(MyControlClass).GetMethod("OnVisibleChanged ",
BindingFlags.NonPublic | BindingFlags.Instance);
Delegate ovcDelegate = Delegate.CreateDelegate(typeof(EventHandler), this,
"VScrollBarValueChanged") as EventHandler;

FieldInfo fi = typeof(Delegate).GetField("_target", BindingFlags.NonPublic |
BindingFlags.Instance);
fi.SetValue(ovcDelegate, myControl);
fi = typeof(Delegate).GetField("_method", BindingFlags.NonPublic |
BindingFlags.Instance);
fi.SetValue(ovcDelegate, ovc);
fi = typeof(Delegate).GetField("_methodPtr", BindingFlags.NonPublic |
BindingFlags.Instance);
fi.SetValue(ovcDelegate, ovc.MethodHandle.Value);
fi = typeof(Delegate).GetField("_methodPtrAux", BindingFlags.NonPublic |
BindingFlags.Instance);
fi.SetValue(ovcDelegate, ovc.MethodHandle.Value);
parentControl.VisibleChanged -= ovcDelegate as EventHandler;

Basically, what I did was I created a dummy delegate that had the same
signature (though I don't think that really matters).

Then, using reflection, I filled in the all the fields of the Delegate with
the information for the event handler I really wanted a delegate for.

Now, as I said, this "almost" worked.

It did appear to successfully remove the old reference. But somehow, it
created an entirely new reference with a call stack leading back to

parentControl.VisibleChanged -= ovcDelegate as EventHandler;

This is according to .NET profiler... The relevant portion of the call stack
is:

MulticastDelegate.RemoveImpl(Delegate)
Delegate.Remove(Delegate, Delegate)
EventHandlerList.RemoveHandler(object, Delegate)
Control.remove_VisibleChanged(EventHandler)

How does that create a reference? Unless it's walking the stack to see where
the call is coming from and saying, "Aha, this is a different class trying
to unsubscribe the original subscription, so let's keep a reference to the
new one..." I don't know. My head is about to pop.

Aug 31 '07 #8
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:11**********************@r34g2000hsd.googlegr oups.com...
On Aug 31, 2:31 pm, "pedrito" <pixbypedrito at yahoo.comwrote:

<snip>
What you *could* do is create a class to encapsulate the method info
and target, and expose a method which has the appropriate signature to
be used as an event handler - that could then call MethodInfo.Invoke.
It would be relatively slow, but it should work.
In reference to this, I'm not sure I understand what you mean. Doesn't the
unsubscription need to have the same underlying function pointer (it appears
that's technically how it's happening underneath with the
Delegate._methodPtr)...

Unless I'm misunderstanding, your method would unsubscribe a different
_methodPtr...

Aug 31 '07 #9
<"pedrito" <pixbypedrito at yahoo.com>wrote:
What you *could* do is create a class to encapsulate the method info
and target, and expose a method which has the appropriate signature to
be used as an event handler - that could then call MethodInfo.Invoke.
It would be relatively slow, but it should work.

In reference to this, I'm not sure I understand what you mean. Doesn't the
unsubscription need to have the same underlying function pointer (it appears
that's technically how it's happening underneath with the
Delegate._methodPtr)...

Unless I'm misunderstanding, your method would unsubscribe a different
_methodPtr...
You'd have to override Equals in your "extra" class, but then it should
be okay, so long as both subscription and unsubscription were done in
the same manner (i.e. both using the proxy).

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Aug 31 '07 #10
Ahh, see, that wouldn't work. I don't do the subscription. The library I'm
using does the subscription. It just never unsubscribes under any condition,
otherwise I'd find whatever method it uses to unsubscribe and call that. But
since it doesn't, I'm trying to figure out a way to force the
unsubscription. The lapsed listener is hanging onto a reference of my
control and I can't get rid of it...
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP********************@msnews.microsoft.com.. .
<"pedrito" <pixbypedrito at yahoo.com>wrote:
What you *could* do is create a class to encapsulate the method info
and target, and expose a method which has the appropriate signature to
be used as an event handler - that could then call MethodInfo.Invoke.
It would be relatively slow, but it should work.

In reference to this, I'm not sure I understand what you mean. Doesn't
the
unsubscription need to have the same underlying function pointer (it
appears
that's technically how it's happening underneath with the
Delegate._methodPtr)...

Unless I'm misunderstanding, your method would unsubscribe a different
_methodPtr...

You'd have to override Equals in your "extra" class, but then it should
be okay, so long as both subscription and unsubscription were done in
the same manner (i.e. both using the proxy).

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Aug 31 '07 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1534
by: Shawn Hogan | last post by:
Hi everyone, I've been trying to execute a control's private event code via reflection from another class with the goal of potentially doing some unit testing. The examples below are trying to...
10
5010
by: Rick Palmer | last post by:
I have an app I'm working on that will allow a user to run one of 5 reports. The report names are in a combobox on my form. I have a sub defined for each report that has the exact same name as is...
0
2061
by: Kamilche | last post by:
''' event.py An event manager using publish/subscribe, and weakrefs. Any function can publish any event without registering it first, and any object can register interest in any event, even...
7
1067
by: guy | last post by:
just discovered that the combination of visual inheritance and reflection can eliminate most of the databinding i would normally do, providing the design is right! and its only taken me 4 years...
4
6281
by: Douglas Peterson | last post by:
I created the following code: private struct StackItem { public EventHandler theEvent, theHandler; public StackItem(EventHandler theEvent, EventHandler theHandler) { this.theEvent = theEvent;...
2
2643
by: mswlogo | last post by:
I looked high and low for code to do this and finally found some VB code that did it right. This is a C# flavor of it. public event EventHandler<EventArgsMyEventToBeFired; public void...
2
2743
by: Grzegorz Danowski | last post by:
Hello, I'd like to hide control if any of its event handlers is forbidden for current user (basing on PrincipalPermissionAttribute). How to list all methods that handle given event? I supposed...
1
1689
by: John Bode | last post by:
I need a way to fake reflection in C++ code that makes as few assumptions about the data types involved as possible. I suspect there is no good answer for what I need to do, but I'll present the...
10
9546
Plater
by: Plater | last post by:
I'm a bit boggled by this since I am rather new to using reflection. I want to attach an event handler via Reflection (which I can do), but I want to NOT have to know the exact event delegate...
0
7205
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7093
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7287
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7348
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
5592
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
4685
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3175
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3166
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
744
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.