使用表达式树动态创建一个方法来执行简单的属性赋值代码:
有什么想法吗?
person.Name = "Joe Bloggs"
,却抛出了NullReferenceException
异常——就像我创建的person
参数没有被传递一样。有什么想法吗?
class Person
{
public string Name { get; set; }
}
static void ExpressionTest()
{
var personParam = Expression.Parameter(typeof(Person), "person");
var block = Expression.Block(new[] { personParam },
Expression.Assign(
Expression.Property(personParam, "Name"), Expression.Constant("Joe Bloggs"))
);
/*
* block.DebugView in debugger shows:
*
* .Block(MyProject.MyNamepace.Person $person) {
* $person.Name = "Joe Bloggs"
* }
*
*/
var method = Expression.Lambda<Action<Person>>(block, personParam).Compile();
var person = new Person();
method(person); // **throws** System.NullReferenceException: ... at lambda_method(Closure , Person )
Debug.WriteLine(person.Name); // I expect this to print "Joe Bloggs"
}
更新
感谢提供这些好的答案,我看到了@decPL的答案,他带领我从Expression.Block
调用中删除了new[] { personParam }
。
现在我完全明白了,Block
会定义变量作用域,而且你需要先定义它们(就像某些语言强制要求的那样)。我的问题是我不需要任何变量,但是被调试器展示的神奇的DebugView
属性所误导。我的想法是它们是参数,而Block
则像函数定义一样:
.Block(MyProject.MyNamepace.Person $person) {
$person.Name = "Joe Bloggs"
}
...当然它不是。正如名称所示,它是一个代码块!