如何将lambda表达式作为返回方法的参数?

时间:2010-07-22 18:26:49

标签: c# .net-4.0 lambda

我希望能够做到这一点:

var test = SomeMethod(s => s.SomeMethod);

通过使方法签名看起来如下所示,我可以使用属性:

SomeMethod<TProperty>(Expression<Func<T, TProperty>> expression)

如何使用方法?我知道这很简单,我只是遗漏了一些小事。

5 个答案:

答案 0 :(得分:1)

这就是你想要的东西吗?

DoSomethingWithAction<T>(Func<T, Action> actionRetriever) { }
DoSomethingWithFunction<T, TResult>(Func<T, Func<TResult>> functionRetriever) { }

你可以这样称呼:

DoSomethingWithAction<ObjectWithMethod>(obj => obj.Method);
DoSomethingWithFunction<ObjectWithProperty>(obj => obj.Property);

答案 1 :(得分:1)

Moq通过要求使用特殊的“标记”对象(例如:

)来删除方法参数来解决此问题
test.Setup(m => m.SomeMethod(It.IsAny<int>()));

顺便提一下,这允许Moq解决方法重载(如果您没有任何所需参数的概念,则单个方法名称不明确。)它们会更进一步并使用它来根据条件实际匹配参数,用于模拟单元测试对象的目的。 source code is available可能会给你一些想法。他们用表达树做各种有趣的诡计。


这是一个基于Moq源的示例(有点被黑了,但显示了如何从表达式中提取方法):

    internal static void ExtractMethod<T>(Expression<Action<T>> expression)
        where T : class
    {
            var methodCall = expression.ToMethodCall();
            var method = methodCall.Method;
            var args = methodCall.Arguments.ToArray();
    }

直接来自Moq来源:

    /// <summary>
    /// Casts the body of the lambda expression to a <see cref="MethodCallExpression"/>.
    /// </summary>
    /// <exception cref="ArgumentException">If the body is not a method call.</exception>
    public static MethodCallExpression ToMethodCall(this LambdaExpression expression)
    {
        Guard.NotNull(() => expression, expression);

        var methodCall = expression.Body as MethodCallExpression;
        if (methodCall == null)
        {
            throw new ArgumentException(string.Format(
                CultureInfo.CurrentCulture,
                Resources.SetupNotMethod,
                expression.ToStringFixed()));
        }

        return methodCall;
    }

这将适用于您的代码,但您必须传递'dummy'参数以允许编译器创建表达式。所以如果你有:

public void SomeMethod(int value, string text) {}

然后你将它传递给:

ExtractMethod(s => s.SomeMethod(0, null));

答案 2 :(得分:0)

这样的东西?

    public SimpleCommand( Predicate<object> canExecuteDelegate, Action<object> executeDelegate )
    {
        CanExecuteDelegate = canExecuteDelegate;
        ExecuteDelegate = executeDelegate;
    }

您需要使用谓词或操作指定功能签名。

答案 3 :(得分:0)

class Program
    {
        public class Test
        {
            public bool SomeMethod(string test)
            {
                return true;
            }
        }

        static void Main(string[] args)
        {

            Test testObj = new Test();


            Func<string, bool> rule1 = AddRule(testObj, x => x.SomeMethod);

            bool rsult = rule1("ttt");

        }

        static Func<string, bool> AddRule<T>( T obj, Func<T,Func<string, bool>> func)
        {
            return func(obj);
        }


}

答案 4 :(得分:0)

我认为,如果不指定方法签名就无法做到这一点:只需考虑重载方法:

void SomeMethod() { }
int SomeMethod(int a, int b) { return 0; }

// ...

var test = TestMethod(s => s.SomeMethod);

编译器如何知道您要测试哪种方法?