2012-07-18 2 views
0

C#에서 식 트리를 작성하는 첫 번째 시도는 너무 잘되지 않습니다. :) 저는 여기에 개념적으로C# 식 트리 : TypeAs 사용

public static object Test<S, D>(S source, Func<D, object> selector) 
    where S : class 
    where D : class 
{ 
    D derived = source as D; 

    object retVal = null; 

    if(derived != null) retVal = selector(derived); 

    return retVal; 
} 

를 복제하기 위해 노력하고있어 C# 코드가있어, 이것은 객체를 가지고 제공된 객체가 파생 클래스의 경우 파생 클래스의 속성을 반환하는 데에 선택을 적용하기위한 것입니다.

는 여기에 지금까지있어 무엇 :

public static object OrderByDerivedProperty<S>(S source, Type derivedType, string fieldName) 
{ 
    ParameterExpression parameter = Expression.Parameter(typeof(S), "source"); 
    UnaryExpression typeAs = Expression.TypeAs(parameter, derivedType); 

    ConstantExpression nullConst = Expression.Constant(null); 
    BinaryExpression isNotNull = Expression.NotEqual(typeAs, nullConst); 

    ParameterExpression varDest = Expression.Variable(derivedType, "varDest"); 
    ParameterExpression retVal = Expression.Variable(typeof(object), "retVal"); 

    BlockExpression block = Expression.Block(
     new[] { varDest, retVal }, 
     Expression.Assign(varDest, typeAs), 
     Expression.Condition(
      isNotNull, 
      Expression.Assign(retVal, Expression.Property(varDest, fieldName)), 
      Expression.Assign(retVal, nullConst) 
      ), 
     retVal 
    ); 

    LambdaExpression lambda = Expression.Lambda(block, new[] { parameter }); 

    return lambda.Compile().DynamicInvoke(source); 
} 

내 표현을 단순화하기 위해 여기에 인수 다소 다른 세트를 사용했습니다.

코드는 derivedType이 사실 S에서 파생 된 Type 인 경우 작동합니다. 그러나 코드가 retVal = null을 반환 할 것으로 예상되는 경우 다음 행에서 불면 :

Expression.Assign(retVal, Expression.Property(varDest, fieldName)), 

fieldName은 varDest의 속성이 아니라고 불평합니다. 그 경우에 맞습니까 ...하지만 테스트 표현식이 틀렸다면 컨디션 표현식의 "참인 경우"평가를하지 않기를 기대했습니다. 그건 분명히 사실이 아닙니다.

표현 트리에 대해 잘 모르는 부분은 책을 가득 채울 것입니다. 그러나 누군가 내가 내가 레일에서 벗어나고 있다고 지적 할 수 있다면 그것을 고맙게 생각할 것입니다. 당신이 이제까지 가지고

답변

0

확실하지 경우이 대답하지만 여기가 중요한 것은 그 널 (null)을 실현하는 것입니다

 public static object OrderByDerivedProperty<TSource>(TSource source, Type derivedType, string propertyOrFieldName) 
     { 
      if (!derivedType.IsClass) 
      { 
       throw new Exception("Derived type must be a class."); 
      } 
      ParameterExpression sourceParameter = Expression.Parameter(typeof(object), "source"); 
      ParameterExpression typeAsVariable = Expression.Variable(derivedType); 
      ParameterExpression returnVariable = Expression.Variable(typeof(object)); 
      BlockExpression block = Expression.Block(
       new[] { typeAsVariable,returnVariable }, 
       Expression.Assign(
        typeAsVariable, 
        Expression.TypeAs(
         sourceParameter, 
         derivedType 
        ) 
       ), 
       Expression.Condition(
        Expression.NotEqual(
         typeAsVariable, 
         Expression.Constant(
          null, 
          derivedType 
         ) 
        ), 
        Expression.Assign(
         returnVariable, 
         Expression.Convert(
          Expression.PropertyOrField(
           typeAsVariable, 
           propertyOrFieldName 
          ), 
          typeof(object) 
         ) 
        ), 
        Expression.Assign(
         returnVariable, 
         Expression.Constant(
          null, 
          typeof(object) 
         ) 
        ) 
       ), 
       returnVariable 
      ); 
      var lambda = Expression.Lambda<Func<object,object>>(block, new[] { sourceParameter }); 
      return lambda.Compile().Invoke(source); 
     } 
+0

필요없는거야, 그것으로 유형 객체 그렇게 널 관련된 유형은 유형의 널 (null)와 동일하지 않은 에스 –