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我同意你的看法,我回答得很简单,因为我认为除了获取他可能拥有的值的所有复杂性之外,他真正需要开始的是知道他需要传递一个表达式,然后开始处理他可能收到的不同场景