代码之家  ›  专栏  ›  技术社区  ›  Max Schmeling

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

  •  2
  • Max Schmeling  · 技术社区  · 15 年前

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

    我可以通过使方法签名如下所示来处理属性:

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

    我怎样才能使它与方法一起工作?我知道这很简单,我只是缺少一些小东西。

    5 回复  |  直到 15 年前
        1
  •  1
  •   Dan Bryant    14 年前

    Moq通过要求使用特殊的“marker”对象来删除方法参数来实现这一点,例如:

    test.Setup(m => m.SomeMethod(It.IsAny<int>()));
    

    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();
        }
    

    直接从最小起订量来源:

        /// <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
  •  1
  •   Dan Tao    15 年前

    你在找这样的东西吗?

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

    你可以这样称呼它们:

    DoSomethingWithAction<ObjectWithMethod>(obj => obj.Method);
    DoSomethingWithFunction<ObjectWithProperty>(obj => obj.Property);
    
        3
  •  0
  •   David Lynch    15 年前

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

    您需要使用谓词或操作指定函数签名。

        4
  •  0
  •   Stan R.    15 年前
    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);
            }
    
    
    }
    
        5
  •  0
  •   MartinStettner    15 年前

    我认为,如果不指定方法签名,就不可能做到这一点:只要想想重载方法:

    void SomeMethod() { }
    int SomeMethod(int a, int b) { return 0; }
    
    // ...
    
    var test = TestMethod(s => s.SomeMethod);
    

    编译器怎么可能知道要测试哪些方法?