Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从操作获取参数<;T>;_C#_Reflection_Action - Fatal编程技术网

C# 从操作获取参数<;T>;

C# 从操作获取参数<;T>;,c#,reflection,action,C#,Reflection,Action,如何将参数传递到操作?代码示例应该强调我试图实现的目标。对不起,有点长 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 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"}
    }
}
类程序
{
静态void Main(字符串[]参数)
{
Foo-Foo=新的Foo();
foo.GetParams(x=>x.Bar(7,“你好”);
}
}
福班
{
公共空栏(int-val,字符串对象){}
}
静态类
{
公共静态对象[]GetParams(此T对象,操作)
{
//返回新对象[]{7,“hello”}
}
}
唯一看起来很有用的选项是GetInvocationList()、方法和目标。但它们似乎都没有包含我想要的数据(我想这是因为我声明操作的方式)。谢谢


编辑:这不是我想要的类型,而是实际值-如代码注释部分所述。

要做到这一点,它实际上应该是一个
表达式-特别是
ResolveMethod
,它返回
out
数组中的值(遍历任何捕获的变量后,等等)

resolvethod
公开后(并删除
resolvethod
上面的所有内容),代码就是:

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;
}
publicstaticobject[]GetParams(这个T对象,表达式动作)
{
忽视这一点的行动;
对象[]args;
ProtoClientExtensions.ResolveMethod(action,out ignoreThis,out args);
返回args;
}

您的操作
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.qux(Application.Current))
应该是这样的:

 public static object[] GetParams<T>(this T obj, Expression<Action<T>> action)
    {
        return ((MethodCallExpression) action.Body).Arguments.Cast<ConstantExpression>().Select(e => e.Value).ToArray();
    }
publicstaticobject[]GetParams(这个T对象,表达式动作)
{
return((MethodCallExpression)action.Body).Arguments.Cast().Select(e=>e.Value).ToArray();
}

您应该进行一些检查,以验证没有无效的内容可以发送到操作中,因为并不是所有内容都将强制转换为MethodCallExpression,但您应该能够从那里开始执行操作

@Henk,事实并非如此,只有当它是foo.GetParams(x=>x.Bar)时才是如此@里奇:你是在追捕被俘的士兵吗?如果你不介意我问的话,你为什么要这样做?@Juliet-我知道各种用途;我最常使用的是RPC拦截,我只是在玩弄编写一个模拟框架(为了好玩,而不是为了现实生活)。这只是我试图找到使用哪些参数的方法之一。语法与Rhino Mocks相同。(我应该注意,
ResolveMethod
也会返回
MethodInfo
——也就是说,您正在调用
Bar
)(哦,我还注释了关于
RpcUtils
,这不重要)谢谢Marc,这工作得很好。我想我需要温习一下表达方式;还有一些@RichK-除了可以这样做之外?好啊其他影响:不能将lambda表达式与语句体一起使用,即lambda与
=>{…}
(大括号很重要)。但是如果您需要委托,只需在expression.re最后一行调用
Compile()
;是的,这是棘手的一点;我引用的代码尝试尽可能多地执行操作而不产生副作用,但在给出的示例中,它将执行
qux
Baz
等,以尝试获取作为args报告的纯值。我尝试了这一点(很好,类似于此),但编译器不喜欢1+位,“仅限赋值、调用、增量等”。@RichK:这在很大程度上取决于
x.Bar
的类型。添加1假定它是
int
,但您的实际类型可能不同。@Marc:虽然实际上可能获得操作中涉及的所有函数的所有参数(即,如果我们考虑加法两个参数函数,表达式树中的所有叶),我真的怀疑这是否有意义。因此我仍然对最初的问题持怀疑态度;我认为OP可能需要更简单的东西。@Marc:IMHO为了返回参数而不产生副作用,我们没有其他选择,也无法将其作为表达式树返回。虽然在大多数实际示例中,对于这种情况是有效的它更复杂-涉及捕获的变量(可能还有多个嵌套的捕获范围)@Marc我同意你的看法,我回答得很简单,因为我认为除了获取他可能拥有的值的所有复杂性之外,他真正需要开始的是知道他需要传递一个表达式,然后开始处理他可能收到的不同场景