![](/img/trans.png)
[英]How do I view the disassembly of a delegate created by compiling an expression tree?
[英]How do I call myself through the delegate generated by the expression tree?
現在我要將表達式樹編譯成委托以動態生成代碼,但是我遇到了問題。 我必須在表達式樹中調用一個方法,它正是尚未動態編譯的表達式樹委托。 我該怎么辦?
我想從表達式樹生成以下代碼:
int i = 0;
Action ac = null;
ac = () =>
{
//if (i-- > 0) condition
ac();
};
以下代碼不起作用,並且提示ac為null
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();
}
表達式問題是你只能按值傳遞變量,所以你需要一些技巧來傳遞引用。 你可以這樣做:
Action<Node> ac = null;
Func<Action<Node>> getAction = () => ac;
並構建這樣的表達式:
ac = () =>
{
//if (i-- > 0) condition
getAction()();
};
另一種選擇是將動作包裝在某個對象中:
Wrapper<Action> = new Wrapper();
ac = () =>
{
//if (i-- > 0) condition
wrapper.Value();
};
wrapper.Value = ac;
這是示例代碼:
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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.