.NET Lambda Pass Method Parameter

Hopefully I missed something obvious, but I was having trouble defining a method that takes a method parameter to retrieve the method information for the passed method. I DO NOT want to 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 ISomeInterface interface. In this case, an example of a method passed in a signature would be:

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

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

There is no standard signature, the method that will be passed will match (except that it will always return an object).

I am currently setting the method as a string (ie "GetNameById"), but I want it to be checked by compile time, so this is the question.

+4
c # lambda
source share
2 answers

This is not particularly nice / free, but if you really want to avoid passing parameter values ​​of a dummy type, you can use an expression that returns a delegate.

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

The implementation of SetResolverMethod will 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 want to create Func<> as a set of overloads for each delegate, you can increase your level of ownership by including method parameter types in the general parameter types of your method.

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

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

I performed three overloads for parameters 0, 1, and 2:

 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); } 
+2
source share

It is impossible to pass only the method itself. You can do this by wrapping the method in the delegate, but for this you need to either specify the SetResolverMethod method to determine the type of this delegate (which you cannot do, because, as you said, no one has a signature) or explicitly specify this type when calling, which would be dirty.

Instead, you can make the SetResolverMethod lambda expression that takes ISomeInterface and returns everything, and passes the actual execution of the method with any arguments as the body of this expression. For instance:

  void SetResolverMethod<T>( Expression<Func<T,object>> expr ); ... SetResolverMethod<ISomeInterface>( x => x.GetNameById(0) ) 

The SetResolverMethod method does not actually execute the expression, but parses it, so your method will not actually be executed.

That's what you need?

+2
source share

All Articles