2010-08-01 2 views
1

나는이처럼 보이는 나무 표현이 있습니다이 표현식 트리에서 Null 참조 예외가 발생하는 이유는 무엇입니까?

.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); 

인보은 다음과 같은 예를 던졌습니다 ce30 그러나 :

개체 참조가 개체의 인스턴스로 설정되지 않았습니다. lambda_method (폐쇄 개체)

에서 나는이 때문에 $result = (MyType2)((MyType1)$instance).Property1; 할당의 일이 생각하지만 표현에 전달되는 인스턴스가 null가 아니기 때문에 이유를 이해하지 않습니다.

ParameterExpression parameter = Expression.Variable(typeof(object)); 

는 단서해야 몸 전체 후에 정의; 것을

답변

3

사실 근본적으로, 당신은 단지 당신이 지나가는 대상을 보지 않고 있습니다. 당신은 단지 instanceParameter을보고 있는데, 이는 귀하의 코드에서 단순히 할당되지 않은 변수입니다.

은 기본적으로 최종 parameter 선언을 삭제하고 변수로 instanceParameter을 선언하지 : 속임수를 썼는지

Expression finalExpression = Expression.Block(
    new[] { resultVariable }, 
    targetFragments); 

MyType2 result = Expression.Lambda<Func<object, MyType2>>(
     finalExpression, instanceParameter).Compile()(instance); 
+0

감사합니다 마크를. 컴파일러가 인수를 따로 전달할 수 없다고 확신 했으므로 (추가 인수를 전달한 경우) 블록에 'instanceParameter'를 추가했습니다. 하지만 지금은 'Func' 타입 매개 변수로 볼 수있는 것이 분명합니다. –

+0

나를 도와 주셔서 다시 한번 감사드립니다. 질문은 http://blog.subspace.nl/post/Getting-rid-of-null-checks-in-property-chains.aspx에서 작성한 블로그 게시물과 밀접한 관련이 있습니다. –