【问题标题】:How to determine anonymous function parameters in c#?如何在c#中确定匿名函数参数?
【发布时间】:2011-12-04 23:33:25
【问题描述】:

给定以下代码,

    public T Execute<T>(Func<T> methodParam)
    {
        return methodParam ();
    }

    public void CallMethodsAnonymously<T>()
    {
        T result =  Execute(() => _service.SomeMethod1());
        T result1 = Execute(() => _service.SomeMethod2(someParm1));
        T result2 = Execute(() => _service.SomeMethod3( someParm1, someParm2));
    }

是否可以从 Execute 方法中检查“methodParam”并提取或确定匿名函数体内的参数数量?例如,是否可以从 Execute 方法中确定 someParam1 和 someParam2 的值?

【问题讨论】:

  • "确定匿名函数体内的参数个数?" Func 主体还是它指向的方法?
  • @jberger - Func methodParam 指向一个没有参数的匿名函数。该匿名函数的主体是我感兴趣的,因为它具有带参数的实际方法调用。

标签: c# delegates anonymous-methods func


【解决方案1】:

我认为这根本不能回答问题。这实际上执行了委托方法并将结果返回到 values[] 对象中。我相信发帖人在问,我也在问如何在委托方法中获取参数的值。

【讨论】:

    【解决方案2】:

    您可以使用Expression API:

    public static T Execute<T>(Expression<Func<T>> methodParam)
    {
        var methodCallExpression = methodParam.Body as MethodCallExpression;
        var method = methodCallExpression.Method;
        var parameters = method.GetParameters();
    
        return methodParam.Compile()();
    }
    

    参数变量将是一个ParameterInfo 对象数组,其中包含您需要的信息。最后,Compile 方法实际上将 Expression 转换为可执行委托。 C# 编译器还允许您使用标准的 lambdas/匿名方法调用带有委托的方法的常规约定来调用此方法。

    编辑:

    我还刚刚注意到您想要一种方法来获取 someParam1 和 someParam2 的实际 。这样做的方法如下:

    private static object GetValue(Expression expression)
    {
        var constantExpression = expression as ConstantExpression;
        if (constantExpression != null)
        {
            return constantExpression.Value;
        }
    
        var objectMember = Expression.Convert(expression, typeof(object));
        var getterLambda = Expression.Lambda<Func<object>>(objectMember);
        var getter = getterLambda.Compile();
        return getter();
    }
    
    
    private static object[] GetParameterValues(LambdaExpression expression)
    {
        var methodCallExpression = expression.Body as MethodCallExpression;
        if (methodCallExpression != null)
        {
            return methodCallExpression.Arguments.Select(GetValue).ToArray();
        }
    
        return null;
    }
    

    所以现在在你的执行方法中,如果你这样做:

    public static T Execute<T>(Expression<Func<T>> methodParam)
    {
        var methodCallExpression = methodParam.Body as MethodCallExpression;
        var method = methodCallExpression.Method;
        var parameters = method.GetParameters();
    
        var values = GetParameterValues(methodParam);
        return methodParam.Compile()();
    }
    

    那么这些值将是一个对象[],其中包含传入的所有实际值。

    【讨论】:

    • MethodCallExpression 在示例中将位于 LambdaExpression
    • 是否可以使用相同的技术为方法动态添加参数?即不必定义: func func func 如果可以使用 Expression 定义一个 Func/delegate 并添加参数,那就太好了动态的。这可能吗?
    • @Bfree 这很好用!谢谢。一个额外的问题。我也想设置参数值。我该怎么做呢?我没有看到使用 Expression api 返回的对象的一种设置器。
    【解决方案3】:

    这不太可能。 Execute 方法被传递了一个委托——在这种情况下是对匿名函数的引用。您要求的是 Execute 方法查看该函数的代码并确定它在做什么。

    这类似于我试图在运行时窥探Random.Next 方法以查看它调用了哪些方法。

    【讨论】:

      【解决方案4】:

      methodParam 调用中没有任何参数。
      代码:() =&gt; _service.SomeMethod1() 基本上“指向”另一个返回 T 的函数。
      () =&gt; _service.SomeMethod1() 相当于:
      () =&gt; { return _service.SomeMethod1(); }

      编辑以实际回答问题(我很傻):
      试试:

      T 结果2 =
         执行(()=>
         {
            [断点]return _service.SomeMethod3(someParm1, someParm2)
         }
      );

      【讨论】:

        猜你喜欢
        • 2012-09-11
        • 2013-02-21
        • 1970-01-01
        • 1970-01-01
        • 2018-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-19
        相关资源
        最近更新 更多