代码之家  ›  专栏  ›  技术社区  ›  SilverX

如何从外部树参数数组中获取运行时参数信息

  •  2
  • SilverX  · 技术社区  · 16 年前

    好的,首先解释一下规则:

    我需要一个函数来构造一个委托,该委托匹配任何委托类型,该委托类型封装了一个主体,该主体调用一个类型为(object)(object[]args)的委托,其中“args”包含在调用期间传递给原始委托的所有参数。

    我的工作到目前为止:

        delegate void TestDelegate(int x, int y);
        delegate object TestDelegate2(object[] args);
    
        static void Main(string[] sargs)
        {
            TestDelegate d = (TestDelegate)CreateAnonymousFromType(typeof(TestDelegate));
            object ret = d.DynamicInvoke(2, 6);
    
            if (ret != null) { Console.WriteLine(ret); }
    
            Console.ReadKey();
        }
    
        static void SpecialInvoke(int x, int y) 
        {
            Console.WriteLine("x: {0}\r\ny: {1}", x, y);
        }
    
        static Delegate CreateAnonymousFromType(Type type)
        {
            MethodInfo method = type.GetMethod("Invoke");
    
            TestDelegate2 _delegate = new TestDelegate2(
                delegate(object[] args) 
                {
                    Console.WriteLine("x: {0}\r\ny: {1}", args[0], args[1]);
                    return "This is the return";
                });
    
    
            var typeargs = CreateArgs(method.GetParameters());
            var argindex = -1;
    
            var tmp = Expression.Parameter(typeof(Object), "tmp");
            var index = Expression.Parameter(typeof(int), "index");
    
            var length = Expression.Constant(typeargs.Length);
    
            var _break = Expression.Label("breakto");
    
            var delegateargs = Expression.Parameter(typeof(object[]), "args");
    
            return Expression.Lambda(
                type,
                Expression.Block(
                    new[] { tmp, index, delegateargs },
                    Expression.Assign(index, Expression.Constant(0)),
                    Expression.Assign(delegateargs, Expression.NewArrayBounds(typeof(Object), length)),
                    Expression.Loop(
                        Expression.IfThenElse(Expression.LessThan(index, length),
                            Expression.Block(
                                Expression.Assign(tmp, Expression.Convert(typeargs[++argindex], typeof(Object))),
                                Expression.Assign(Expression.ArrayAccess(delegateargs, index), tmp),
                                Expression.PostIncrementAssign(index)
                            ),
                            Expression.Break(_break)
                        ),
                        _break
                    ),
                    Expression.Call(_delegate.Method, delegateargs)
                ),
                typeargs
            ).Compile();
        }
    
        static ParameterExpression[] CreateArgs(ParameterInfo[] _params)
        {
            ParameterExpression[] ret = new ParameterExpression[_params.Length];
    
            for (int i = 0; i < ret.Length; i++)
                ret[i] = Expression.Parameter(_params[i].ParameterType, _params[i].Name);
    
            return ret;
        }
    

    现在这一排序工作…我只得到传递给委托“testdelegate2”的typeargs[0]的值,对于参数x和y,运行时的“args”参数是object[]2,2,在我的生命中,找不到在参数迭代范围内增加“argindex”的方法…编译时的参数计数不确定。 有人知道我怎么解决这个问题吗?

    我试过使用expression.newarrayinit(typeof(object),typeargs)复制参数数组,但没有说它不能使用int32初始化对象数组。

    我也尝试过: var参数=表达式。常量(typeargs);

    访问“index”处“arguments”的值,但这会生成字符串“x”和“y”。显然,这些论点的名字,而不是它们的价值观。

    老实说,这是我第一次尝试使用表达式树,所以有什么帮助。不管多小。会很感激的。

    谢谢您。

    1 回复  |  直到 16 年前
        1
  •  2
  •   Quartermeister    16 年前

    我觉得你的表达方式是对的。新的。可以使用表达式修复“System.Int32”类型的表达式不能用于初始化“System.Object”类型的数组错误。转换为插入每个参数的转换:

    var typeargs = CreateArgs(method.GetParameters());
    return Expression.Lambda(
        type,
        Expression.Call(_delegate.Method, Expression.NewArrayInit(typeof(object),
            typeargs.Select(arg => Expression.Convert(arg, typeof(object)))
            )),
        typeargs
    ).Compile();