"Jon Skeet [C# MVP]" <sk***@pobox.co mwrote in message
news:11******** **************@ r34g2000hsd.goo glegroups.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.Invo ke.
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(MyContro lClass).GetMeth od("OnVisibleCh anged",
BindingFlags.No nPublic | BindingFlags.In stance);
Delegate ovcDelegate = Delegate.Create Delegate(typeof (EventHandler), this,
"VScrollBarValu eChanged") as EventHandler;
FieldInfo fi = typeof(Delegate ).GetField("_ta rget", BindingFlags.No nPublic |
BindingFlags.In stance);
fi.SetValue(ovc Delegate, myControl);
fi = typeof(Delegate ).GetField("_me thod", BindingFlags.No nPublic |
BindingFlags.In stance);
fi.SetValue(ovc Delegate, ovc);
fi = typeof(Delegate ).GetField("_me thodPtr", BindingFlags.No nPublic |
BindingFlags.In stance);
fi.SetValue(ovc Delegate, ovc.MethodHandl e.Value);
fi = typeof(Delegate ).GetField("_me thodPtrAux", BindingFlags.No nPublic |
BindingFlags.In stance);
fi.SetValue(ovc Delegate, ovc.MethodHandl e.Value);
parentControl.V isibleChanged -= 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.V isibleChanged -= ovcDelegate as EventHandler;
This is according to .NET profiler... The relevant portion of the call stack
is:
MulticastDelega te.RemoveImpl(D elegate)
Delegate.Remove (Delegate, Delegate)
EventHandlerLis t.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.