Have you ever wondered whether there is an existing delegate somewhere in the BCL that meets your needs? Ever wish you could search by delegate signature and find any matching delegate? Me too. After all, why create yet another type when an existing type will suffice? This is especially true when you're not using the delegate as any part of your public API.
One way I've found to do this is by using the Code Search add in for Reflector. The Code Search add in allows you to search through disassembled code for matches to a regular expression that you supply. It has some limitations that we have to work around, but we can still get the job done.
Firstly, it only searches from the currently selected node in the left-hand tree view and down. Since there is no root node, you can only search one assembly at a time, which is a minor inconvenience. For example:
Since mscorlib is selected in the tree view, it is the only assembly that will be searched. Typically you will want to search for delegates at least in mscorlib and System, and sometimes you will want to search other assemblies that your project references. Therefore, you will need to repeat the search a number of times.
The second - and more annoying - limitation is that type declarations are not searched, only the members in types are. This means we can't search for a delegate declaration like "public delegate ..." but instead have to find something common to the implementation of all delegates that we can use to identify them. Fortunately, all delegates will have a method of form:
public virtual ReturnType Invoke(Parameters);
Therefore we have a handle with which we can find delegates. However, we will get some false positives, such as finding non-public delegates and finding methods called
Invoke() that aren't part of a delegate type (we could probably work around that, but it wouldn't be worth the effort). That said, it's simple to identify and ignore these false positives.
Suppose we want to find an existing delegate with this signature:
public delegate void DelegateName(object argName);
We don't care what the delegate is called, nor what the argument is called. All we want is a delegate that takes a single argument of type
object and returns
void. We can find all matching delegates with this regular expression:
public virtual void Invoke\(object [^,]*?\);
Here are the results from running this query against mscorlib:
There are a couple of false positives (
DeserializationEventHandler are both
internal) but we can see that there are a bunch of delegates we could use to satisfy our requirements.
Now what about a delegate matching this signature:
public delegate bool DelegateName(Type argName1, object argName2);
We can use an expression of
public virtual bool Invoke\(Type [^,]*?, object [^,]*?\); to find a suitable delegate called
Finding generic delegates becomes problematic:
public delegate void DelegateName<T>(object argName1, T argName2);
To match the above delegate, we need to find a method like this:
public virtual void Invoke(object argName1, T argName2);
Problem is, we don't care whether the delegate declared the generic type as
T, or something else (like
TEventArgs in the
EventHandler<TEventArgs> delegate). So the best we can do is search for a two argument
Invoke() method whose first parameter is of type
One final tip: we can find all delegates in a given assembly by using the expression
public virtual \S*? Invoke\(.*?\); as pictured below (again, against mscorlib):