views:

111

answers:

5

i have a method that takes as a parameter an expression because I need the method string name, and I don't care about the parameters of that method, is it possible to do that ?

+2  A: 

I don't think that there is. You can however make a generic helper method that you can put in place of the parameters:

public T Any<T>(){
    return default(T);
}

and you can call it like so:

YourMethod((YourClass yc) => yc.SomeMethod(Any<SomeClass>(), Any<SomeOtherClass>());
klausbyskov
:) good idea, but I would rather put some nulls, and zeroes
Omu
+1  A: 

You can use this method without parameters but parentheses (even empty) are required, because without them you tell the compiler to access a property of that name.

RaYell
+2  A: 

Yes, it's possible. Here is a concept proof test.

private static T RunExpression<T>(Expression<Func<T>> run )
        {
            var callExpression = (MethodCallExpression) run.Body;

            var procedureName = callExpression.Method.Name;

            Trace.WriteLine(procedureName);

            foreach (var argument in callExpression.Arguments)
            {
                Trace.WriteLine(argument);
            }

            Trace.WriteLine(callExpression.Arguments.Count);

                    // Some really wicked stuff to assign out parameter
                    // Just for demonstration purposes

            var outMember = (MemberExpression)callExpression.Arguments[1];

            var e = Expression.Lambda<Func<object>>(outMember.Expression);
            var o = e.Compile().Invoke();

            var prop = o.GetType().GetField("s");
            prop.SetValue(o, "Hello from magic method call!");

            Trace.WriteLine(run.Body);
            return default(T);
        }



[TestMethod]
        public void TestExpressionInvocation()
        {
            var action = new MyActionObject();

            string s = null;
            RunExpression(() => action.Create(1, out s));

            Assert.AreEqual("Hello from magic method call!", s);
        }
George Polevoy
I actually wanted something like this: var methodName = RunExpression<MyClass>(o => o.Method);
Omu
A: 

You can use something like: (credits go to klausbyskov) But it's less verbose.

Also you will need to provide overloads for various argument lists.

 [TestClass]
 public class TestExpressions
 {
  public class MyClass
  {
   public bool MyMethod(string arg)
   {
    throw new NotImplementedException();
   }
  }

  private static string UseExpression<T, Ta1>(Expression<Action<T,Ta1>> run)
  {
   return ((MethodCallExpression)run.Body).Method.Name;
  }

  [TestMethod]
  public void TestExpressionParser()
  {
   Assert.AreEqual("MyMethod",

   UseExpression<MyClass,string>((c,fakeString) => c.MyMethod(fakeString)));
  }
 }
George Polevoy
+1  A: 

The easiest way to do this doesn't even use expression trees:

void Main()
{
    Console.Out.WriteLine(GetNameOfMethod(new Action(Main)));
    Console.Out.WriteLine(GetNameOfMethod(new Func<Delegate, string>(GetNameOfMethod)));
    Console.Out.WriteLine(GetNameOfMethod(new Func<int, short, long>(AddNumber)));
    Console.Out.WriteLine(GetNameOfMethod(new Action<int, short>(SwallowNumber)));
}

string GetNameOfMethod(Delegate d){
    return d.Method.Name;
}

long AddNumber(int x, short y){ return x+y; }
void SwallowNumber(int x, short y){}

yields:

Main 
GetNameOfMethod 
AddNumber
SwallowNumber

I use this to build a BDD framework on http://storyq.codeplex.com.

Click here to see the file where I do this.

Rob Fonseca-Ensor
If you are using method group, it could be even less verbose GetNameOfMethod(Main), but what about using method group outside the scope of the class?
George Polevoy
GetNameOfMethod(Main) fails to compile because the type of Delegate isn't specified. As long as the method is accessible to the thing *calling* GetNameOfMethod this will work fine - you just have to pick an appropriate Delegate type...
Rob Fonseca-Ensor