我有一个树表达式,如下所示:
.Block( System.Object $instance, MyType2 $result) { $result = (MyType2)((MyType1)$instance).Property1; .Goto return { }; .Label .LabelTarget useDefault:; $result = .Default(MyType2); .Label .LabelTarget return:; $result }
public class MyType1 { public MyType2 Property1 { get; set; } } public class MyType2 { }
最后,这就是我构建、编译和调用表达式树的方式(它不会像这样运行,因为我省略了一些代码来简化事情):
object instance = new MyType1(); Expression expression = ... // n => n.Property1 ParameterExpression instanceParameter = Expression.Variable( typeof(object), "instance"); ParameterExpression resultVariable = Expression.Variable( typeof(MyType2), "result"); LabelTarget useDefaultLabel = Expression.Label("useDefault"); LabelTarget returnLabel = Expression.Label("return"); List<Expression> targetFragments = new List<Expression>(); MemberInfo memberInfo = (MemberInfo)expression.Body.Member; MemberExpression member = ConstantExpression.MakeMemberAccess( Expression.Convert(instanceParameter, memberInfo.DeclaringType), memberInfo); targetFragments.Add( Expression.Assign( resultVariable, Expression.Convert(member, typeof(MyType2)))); targetFragments.Add(Expression.Goto(returnLabel)); targetFragments.Add(Expression.Label(useDefaultLabel)); targetFragments.Add(Expression.Assign(resultVariable, Expression.Default(typeof(MyType2)))); targetFragments.Add(Expression.Label(returnLabel)); targetFragments.Add(resultVariable); Expression finalExpression = Expression.Block( new[] { instanceParameter, resultVariable }, targetFragments); ParameterExpression parameter = Expression.Variable(typeof(object)); MyType2 result = Expression.Lambda<Func<T, MyType2>>(expression, parameter) .Compile()(instance);
对象引用未设置为对象的实例。at lambda_方法(闭包,对象)
我认为这是因为 $result = (MyType2)((MyType1)$instance).Property1; null .
$result = (MyType2)((MyType1)$instance).Property1;
null
事实是:
ParameterExpression parameter = Expression.Variable(typeof(object));
instanceParameter ,它(在代码中)只是一个未赋值的变量。
instanceParameter
基本上,放弃决赛 parameter 瞬时参数 作为变量:
parameter
瞬时参数
Expression finalExpression = Expression.Block( new[] { resultVariable }, targetFragments); MyType2 result = Expression.Lambda<Func<object, MyType2>>( finalExpression, instanceParameter).Compile()(instance);