0

私の最初の試みである C# での式ツリーの作成はあまりうまくいきません :)。複製しようとしているC#コードは次のとおりです

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;
}

概念的には、これはオブジェクトを受け取り、それにセレクターを適用して、提供されたオブジェクトが派生クラスの場合、派生クラスのプロパティを返すことを目的としています。

ここに私がこれまでに持っているものがあります:

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 のプロパティではないことを訴えています。その場合は正しい...しかし、テスト式が偽の場合、条件式の「真の場合」アームが評価されないことを期待していました。明らかにそうではありません。

式ツリーについて私が知らないことは、(それ以上の) 本を埋めるでしょう。しかし、誰かが私がレールから外れているところを指摘できれば、私はそれを感謝します.

4

1 に答える 1