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 ?
views:
111answers:
5
+1
Q:
o => o.MethodWithParamters | is it possible to use a method in a lambda without () and paramteters
+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
2010-02-01 10:06:14
:) good idea, but I would rather put some nulls, and zeroes
Omu
2010-02-01 12:00:46
+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
2010-02-01 10:06:22
+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
2010-02-01 10:29:32
I actually wanted something like this: var methodName = RunExpression<MyClass>(o => o.Method);
Omu
2010-02-01 11:55:48
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
2010-02-01 13:44:27
+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.
Rob Fonseca-Ensor
2010-02-01 13:54:16
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
2010-02-01 14:21:18
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
2010-02-01 14:48:07