4

I hope i'm missing something obvious, but I'm having some troubles defining a method that takes a parameter of a method to fetch the method information for the passed method. I do NOT want actually execute the method.

I want to be able to do:

  busObject.SetResolverMethod<ISomeInterface>(x=>x.GetNameById);

Where GetNameById is a method defined on the interface ISomeInterface. In this case, an example of the method being passed in's signature would be:

 MyVarA GetNameById(int id){ .... }

In the above example, the SetResolverMethod's body should be able to return / store the string "GetNameById".

There is no standard signature the method being passed in will conform to (except that it will always return an object of some kind).

Currently I'm setting the method as a string (i.e. "GetNameById"), but I want it to be compile time checked, hence this question.

4
  • If there's no standard signature then how can you ever call it? Unless you cheat at force a cast to something that does have a standard signature (which would be scary). Commented May 31, 2010 at 2:23
  • If there's no standard signature of the method being passed in, what do you expect to be checked at compile time? Commented May 31, 2010 at 2:23
  • @colithium - I never said I do want to call it. Its the method name that i need. i.e. I want MethodInfo basically. Commented May 31, 2010 at 2:28
  • @lc I just dont want to use strings, so if someone refactors the method name, it will be refactored here too. Commented May 31, 2010 at 2:29

2 Answers 2

2

It's not particularly pretty/fluent but if you really want to avoid having to pass dummy parameter values then you can use an expression that returns a delegate.

SetResolverMethod<ISomeInterface>(x => new Func<int, MyVarA>(x.GetNameById));

The SetResolverMethod implementation would look something like this:

public void SetResolverMethod<T>(Expression<Func<T, Delegate>> expr)
{
    var unary = (UnaryExpression) expr.Body;
    var methodCall = (MethodCallExpression) unary.Operand;
    var constant = (ConstantExpression) methodCall.Arguments[2];
    var method = (MethodInfo) constant.Value;
    Console.WriteLine(method.Name);
}

Edit: If you're willing to create as set of overloads for each Func<> delegate, you can improve the fluency by including the method parameter types in the generic parameter types of your method.

p.SetResolverMethod<ISomeInterface, int, MyVarA>(x => x.GetNameById);

As you can see, the caller no longer needs to specify a delegate type, thus saving around 8 characters.

I've implemented three overloads for 0, 1 and 2 parameters:

public void SetResolverMethod<T, TResult>(Expression<Func<T, Func<TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

public void SetResolverMethod<T, T1, TResult>(Expression<Func<T, Func<T1, TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

public void SetResolverMethod<T, T1, T2, TResult>(Expression<Func<T, Func<T1, T2, TResult>>> expr)
{
    SetResolverMethod((LambdaExpression) expr);
}

private void SetResolverMethod(LambdaExpression expr)
{
    var unary = (UnaryExpression) expr.Body;
    var methodCall = (MethodCallExpression) unary.Operand;
    var constant = (ConstantExpression) methodCall.Arguments[2];
    var method = (MethodInfo) constant.Value;
    Console.WriteLine(method.Name);
}
Sign up to request clarification or add additional context in comments.

Comments

2

There is no way to pass just the method itself. You could do it by wrapping the method in a delegate, but for that, you have to either have the SetResolverMethod method define the type of that delegate (which you can't do, because, as you said, there is no one signature), or explicitly specify that type when calling, which would be dirty.

What you could do instead is have the SetResolverMethod take a lambda expression that takes ISomeInterface and returns whatever, and pass the actual execution of the method with whatever arguments as the body of that expression. Like so:

    void SetResolverMethod<T>( Expression<Func<T,object>> expr );

    ...

    SetResolverMethod<ISomeInterface>( x => x.GetNameById(0) )

The SetResolverMethod method will not actually execute the expression, only analyze it - therefore, your method will not actually be executed.

Is this what you need?

2 Comments

Yeah that is the best that I could come up with as well. Was trying to avoid having to populate dummy parameters. Cheers.
Well, as I said - you can't really pass just a reference to a method without explicitly specifying it's signature (and even more - delegate type) somewhere. And in addition, think about this: what's going to happen with overloads? How are you going to distinguish between them without specifying parameters? So dummy parameters are pretty much your only way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.