views:

194

answers:

3

Hi,

I've got a class that's got a bunch of public methods, and I'd like to reflect over it to find the set of member methods that could be used as a particular delegate.

For example:

delegate void InterestingFunc(int i);

class Entity
{
    public void F();
    public void G();
    public void H(int i);
    public void X(int i);
}

Can I use Type.FindMembers() to pull out the set { H, X }? If so, how? Is there a better way?

+4  A: 

There is no inherent query support in Type which will find methods based on a delegate signature. You would need to hand code a search method which loops through methods and properties manually comparing the signatures to that of the proposed delegate.

This itself is a non-trivial operation as you need to take generics into account with your solution.

JaredPar
+1  A: 

This itself is a non-trivial operation as you need to take generics into account with your solution.

100% correct -- not to mention ref/out parameters, param[] modifiers, as well as unsafe pointers.

One non-optimal option is to apply Delegate.CreateDelegate to each method in Entity, taking note of when the construction fails. The failures denote the incompatible methods.

Again, you will likely have to do some work to handle the case of generic methods.

Steve Guidi
+1  A: 

Here's a start:

   MethodInfo[] FindMethods(Type delegateType, Type sourceType)
    { 
      var dInfo       = delegateType.GetMethod("Invoke");
      var dParamTypes = delegateInfo.GetParameters().Select(p=>p.ParameterType);

      var methods = from methodInfo in sourceType.GetMethods()
                    let mParamTypes = methodInfo.GetParameters()
                                                .Select(p=>p.ParameterType)
                    where    methodInfo.ReturnType == delegateInfo.ReturnType
                          && mParamTypes.SequenceEqual(dParamTypes)
                    select methodInfo;

      return methods.ToArray();
    }

It can be expanded to take into account generics, ref/out parameters, and anything else. Test-driven development would be particularly helpful here.

Mark Cidade