如何将参数传递到Action<T>
?代码示例应该突出我想要实现的目标。对不起,这有点长。
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"}
}
}
看起来有用的唯一选项是GetInvocationList(),Method和Target。但它们似乎都没有包含我所追求的数据(我认为这是因为我宣布了Action的方式)。感谢
编辑:这不是我想要的类型,它是实际值 - 如注释位代码中所述。
答案 0 :(得分:9)
要做到这一点,它实际上应该是Expression<Action<T>>
。然后是分解表达式的情况。幸运的是,我在protobuf-net here中拥有了所有代码 - 特别是ResolveMethod
,它返回out
数组中的值(在遍历任何捕获的变量之后等)。
将ResolveMethod
公开(并删除上面的所有内容 ResolveMethod
)后,代码就是:
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;
}
答案 1 :(得分:5)
它应该是这样的:
public static object[] GetParams<T>(this T obj, Expression<Action<T>> action)
{
return ((MethodCallExpression) action.Body).Arguments.Cast<ConstantExpression>().Select(e => e.Value).ToArray();
}
你应该做一些检查以确认没有任何无效的内容可以发送到动作中,因为并不是所有内容都会被转换为MethodCallExpression,但你应该可以从那里开始
答案 2 :(得分:3)
您的操作x => x.Bar(7, "hello")
可以重写为
void action(T x)
{
return x.Bar(7, "hello");
}
现在很清楚,7
和"hello"
不是操作的参数,只有x
。
要访问7
和"hello"
,您需要访问该表达式,就像@Marc建议的那样。但是,目前尚不清楚代码应如何处理更复杂的表达式,例如x => 1 + x.Bar(7, x.Baz("hello", x.Quux(Application.Current)))
。