[...]
I make a MenuStrip using the Ide. I want to clone one of the
ToolStripMenuItems. To do that I need to get the EventHandler delegate it
has stored for click. But I can't seem to do that. If you know how to do
that I'd appreciate learning how - I've been trying for a couple of days
now.
That depends on what you mean. If you want the delegate stored for the
Click event, there is no direct way to do that. It's private to the class
that declares the event, which means that if you can't modify the actual
class that declares the event, there's no way to get at the value via
normal C# syntax. And of course, you can't modify the ToolStripMenuItem
class.
You _might_ be able to do it via reflection (see
http://msdn2.microsoft.com/en-us/library/system.reflection.aspx), which
doesn't do anything to prevent you from accessing private members.
However, even assuming it works IMHO that would be a poor solution. It's
less efficient, and more importantly it obscures the relatively abnormal
use of the Click event by hiding it in whatever code does the reflection.
It's more awkward to create a subclass that exposes a new event that you
can clone, or to create a subclass that has a separate method for
subscribing to the Click event in which you make a copy of the delegate
passed in, or any of the other techniques you might use to do this.
But in my own personal opinion, that awkwardness is actually a good thing,
as it highlights the unusual nature of the implementation.
As far as using reflection goes, keep in mind also that doing so would be
very fragile. You'd be relying on a specific implementation, which could
change with any revision of .NET. If and when it does, your own code will
break.
I don't know how the ToolStripMenuItem deals with its events, but it's my
recollection that the Control class does _not_ use the default C# event
declarations. Instead, it implements its own add/remove methods for each
event, and stores event subscribers in a separate data structure (probably
a dictionary or something like that). It does this because in the vast
majority of cases, almost every event remains unsubscribed for the entire
lifetime of the control, and so not having a separate field for every
single event saves a lot of memory.
If the ToolStripMenuItem handles events like this now, then you're already
in for an uphill battle hooking into that code (you'll probably want to
use Reflector or something similar to figure out how the events are being
stored). And even if it doesn't do this now, it could in the future.
Either way, with every revision of .NET, you run the risk of your code no
longer working with the new implementation of ToolStripMenuItem.
A number of non-reflective solutions have been posted in this thread, and
there are plenty of variations on those themes. None will do _exactly_
what you're asking, but all will accomplish very much the same thing. I
strongly recommend you stick with one of these alternative approaches, and
forget about trying to get at the actual value of the Click delegate in
the ToolStripMenuItem class itself. It's a private member and for better
or worse, you're not supposed to have it.
Pete