o => o.MethodWithParameters |Можно ли использовать метод в лямбда без () и параметров - PullRequest
1 голос
/ 01 февраля 2010

У меня есть метод, который принимает в качестве параметра выражение, потому что мне нужно имя строки метода, и меня не волнуют параметры этого метода, возможно ли это сделать?

Ответы [ 5 ]

2 голосов
/ 01 февраля 2010

Самый простой способ сделать это, даже не используя деревья выражений:

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){}

Выходы:

Main 
GetNameOfMethod 
AddNumber
SwallowNumber

Я использую это для создания BDD-фреймворка на http://storyq.codeplex.com.

Нажмите здесь, чтобы увидеть файл, где я делаю это.

2 голосов
/ 01 февраля 2010

Да, это возможно. Вот концептуальный тест.

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);
        }
2 голосов
/ 01 февраля 2010

Я не думаю, что есть. Однако вы можете создать общий вспомогательный метод, который вы можете поместить вместо параметров:

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

и вы можете назвать это так:

YourMethod((YourClass yc) => yc.SomeMethod(Any<SomeClass>(), Any<SomeOtherClass>());
1 голос
/ 01 февраля 2010

Вы можете использовать этот метод без параметров, но скобки (даже пустые) обязательны, потому что без них вы указываете компилятору обращаться к свойству с таким именем.

0 голосов
/ 01 февраля 2010

Вы можете использовать что-то вроде: (кредиты идут на клаусбысков) Но это менее многословно.

Также вам потребуется предоставить перегрузки для различных списков аргументов.

 [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)));
  }
 }
...