Get Parameters from Action<T>

微笑、不失礼 提交于 2019-12-18 16:54:46

问题


How do I get the parameters passed into an Action<T> ? The code example should highlight what I'm trying to achieve. Sorry that it's a little bit long.

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo();
        foo.GetParams(x => x.Bar(7, "hello"));
    }
}

class Foo
{
    public void Bar(int val, string thing) { }
}

static class Ex
{
    public static object[] GetParams<T>(this T obj, Action<T> action)
    {
        // Return new object[]{7, "hello"}
    }
}

The only options that look vaguely useful are GetInvocationList(), Method and Target. But none of them seem to contain the data I'm after (I think it's because of the way I've declared the Action). Thanks

EDIT: It's not the types I want, it's the actual values - as noted in the commented bit of code.


回答1:


To do that, it should actually be an Expression<Action<T>>. Then it is a case of decomposing the expression. Fortunately I have all the code for that over in protobuf-net, here - in particular ResolveMethod, which returns the values in the out array (after walking any captured variables, etc).

After making ResolveMethod public (and removing everything above ResolveMethod), the code is just:

public static object[] GetParams<T>(this T obj, Expression<Action<T>> action)
{
    Action ignoreThis;
    object[] args;
    ProtoClientExtensions.ResolveMethod<T>(action, out ignoreThis, out args);
    return args;
}



回答2:


It should be something like this:

 public static object[] GetParams<T>(this T obj, Expression<Action<T>> action)
    {
        return ((MethodCallExpression) action.Body).Arguments.Cast<ConstantExpression>().Select(e => e.Value).ToArray();
    }

you should do some checking to verify that nothing invalid can sent into the action, as not everything is going to cast to a MethodCallExpression, but you should be able to follow from there




回答3:


Your action x => x.Bar(7, "hello") can be rewritten as

void action(T x)
{
    return x.Bar(7, "hello");
}

It's clear now that 7 and "hello" are not the parameters of the action, only x is.

In order to get access to 7 and "hello", you need an access to the expression, like what @Marc suggests. However it's not clear how your code should handle more complicated expressions, like x => 1 + x.Bar(7, x.Baz("hello", x.Quux(Application.Current))).



来源:https://stackoverflow.com/questions/4361314/get-parameters-from-actiont

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!