1

特定のメンバーに対して実行時にコンパイル済みの getter メソッドを生成しています。今のところ、私のコードは getter メソッドの結果が文字列であると想定しています (テストではうまくいきました)。ただし、私が作成したカスタム コンバーター クラスでこれを機能させたいと考えています。以下を参照してください。追加した「ConverterBase」リファレンスを参照してください。

コンバーター クラスへの呼び出しを式ツリーに追加する方法がわかりません。

    public Func<U, string> GetGetter<U>(MemberInfo info)
    {
        Type t = null;
        if (info is PropertyInfo) 
        {
            t = ((PropertyInfo)info).PropertyType;
        }
        else if (info is FieldInfo)
        {
            t = ((FieldInfo)info).FieldType;
        }
        else
        {
            throw new Exception("Unknown member type");
        }

        //TODO, replace with ability to specify in custom attribute
        ConverterBase typeConverter = new ConverterBase();

        ParameterExpression target = Expression.Parameter(typeof(U), "target");
        MemberExpression memberAccess = Expression.MakeMemberAccess(target, info);

        //TODO here, make the expression call "typeConverter.FieldToString(fieldValue)"

        LambdaExpression getter = Expression.Lambda(memberAccess, target);

        return (Func<U, string>)getter.Compile();
    }

2 番目の TODO エリアに何を入れるかを探しています (最初の TODO エリアは処理できます:))。

結果のコンパイル済みラムダは、型 U のインスタンスをパラメーターとして取り、指定されたメンバー アクセス関数を呼び出してから、コンバーターの "FieldToString" メソッドを結果と共に呼び出し、結果の文字列を返す必要があります。

4

2 に答える 2

5

(通常の C# の場合) 式を評価する対象を説明できますか? 私は簡単に式を書くことができます - 私は質問を完全には理解していません...

(コメントを編集)-その場合、次のようになります。

    ConverterBase typeConverter = new ConverterBase();
    var target = Expression.Parameter(typeof(U), "target");
    var getter = Expression.MakeMemberAccess(target, info);
    var converter = Expression.Constant(typeConverter, typeof(ConverterBase));

    return Expression.Lambda<Func<U, string>>(
    Expression.Call(converter, typeof(ConverterBase).GetMethod("FieldToString"),
        getter), target).Compile();

または、型がバインドを拒否する場合は、キャスト/変換を挿入する必要があります。

    MethodInfo method = typeof(ConverterBase).GetMethod("FieldToString");
    return Expression.Lambda<Func<U, string>>(
        Expression.Call(converter, method,
            Expression.Convert(getter, method.GetParameters().Single().ParameterType)),
            target).Compile();
于 2008-11-26T12:22:38.010 に答える
4

たとえば、Expression.Constant を使用して、オブジェクトを ExpressionConstant でラップする必要があります。次に例を示します。

class MyConverter
{
    public string MyToString(int x)
    {
        return x.ToString();
    }
}

static void Main()
{
    MyConverter c = new MyConverter();

    ParameterExpression p = Expression.Parameter(typeof(int), "p");
    LambdaExpression intToStr = Expression.Lambda(
        Expression.Call(
            Expression.Constant(c),
            c.GetType().GetMethod("MyToString"),
            p),
        p);

    Func<int,string> f = (Func<int,string>) intToStr.Compile();

    Console.WriteLine(f(42));
    Console.ReadLine();
}
于 2008-11-26T12:17:51.763 に答える