首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何通过表达式树生成的委托调用自己?

如何通过表达式树生成的委托调用自己?
EN

Stack Overflow用户
提问于 2019-01-15 15:12:23
回答 1查看 115关注 0票数 5

现在我将把表达式树编译成一个委托来动态生成代码,但是我有一个问题。我必须调用表达式树中的方法,这正是尚未动态编译的表达式树委托。我该怎么办?

我想从表达式树中生成以下代码:

代码语言:javascript
复制
int i = 0;
Action ac = null;

ac = () =>
{
    //if (i-- > 0)  condition
        ac();
};

以下代码不起作用,并将提示ac is null

代码语言:javascript
复制
static Action ac = Build();
static Action Build()
{
    return Expression.Lambda<Action>(
        Expression.Call(
            Expression.Constant(ac), //throw ac is null
            typeof(Action).GetType().GetMethod("Invoke")
        )
    ).Compile();
}
EN

回答 1

Stack Overflow用户

发布于 2019-09-11 20:12:32

表达式的问题是你只能通过值来传递变量,所以你需要一些技巧来传递引用。您可以这样做:

代码语言:javascript
复制
Action<Node> ac = null;
Func<Action<Node>> getAction = () => ac;

并构建这样的表达式:

代码语言:javascript
复制
ac = () =>
{
    //if (i-- > 0)  condition
        getAction()();
};

另一个选择是将action包装在某个对象中:

代码语言:javascript
复制
Wrapper<Action> = new Wrapper();
ac = () =>
{
    //if (i-- > 0)  condition
        wrapper.Value();
};
wrapper.Value = ac;

以下是示例代码:

代码语言:javascript
复制
    class Wrapper<T>
    {
        public T Value { get; set; }
    }

    static void Main(string[] args)
    {
        Node root = new Node
        {
            Name = "First",
            Next = new Node {Name = "Second"}
        };

        var method = Build();
        method(root);
    }

    class Node
    {
        public string Name { get; set; }
        public Node Next { get; set; }
    }

    static Action<Node> Build()
    {
        var wrapper = new Wrapper<Action<Node>>();
        var param = Expression.Parameter(typeof(Node), "node");
        var expr = Expression.Lambda<Action<Node>>(
            Expression.Block(
                // Console.WriteLine("Node name: {0}", node.Name);
                Expression.Call(
                    typeof(Console), 
                    "WriteLine", 
                    Type.EmptyTypes, 
                    Expression.Constant("Node name: {0}"), 
                    Expression.Property(param, "Name")
                ),
                // if (node.Next != null) wrapper.Value(node.Next)
                Expression.IfThen(
                    Expression.ReferenceNotEqual(Expression.Property(param, "Next"), Expression.Constant(null)),
                    // wrapper.Value(node.Next)
                    Expression.Invoke(
                        // wrapper.Value
                        Expression.Property(Expression.Constant(wrapper), "Value"),
                        // node.Next
                        Expression.Property(param, "Next")
                    )
                )
            ),
            param
        );

        return wrapper.Value = expr.Compile();
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54194178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档