Frage

Ich bin Erzeugung kompilierte Getter-Methoden zur Laufzeit für ein bestimmtes Mitglied. Gerade jetzt, mein Code geht davon aus, dass nur das Ergebnis der Getter-Methode ist ein String (arbeitete gut zum Testen). Allerdings würde ich diese Arbeit mit einer benutzerdefinierten Konverter Klasse machen wie ich geschrieben habe, siehe unten, „ConverterBase“ Referenz, die ich hinzugefügt haben.

ich kann nicht herausfinden, wie der Anruf an die Konverter-Klasse meines Ausdrucksbaum hinzuzufügen.

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

Ich bin auf der Suche für das, was in dem zweiten TODO Bereich setzen (ich kann die ersten Griff:)).

Das resultierende kompilierte lambda sollte eine Instanz des Typs U als param nehmen, rufen die angegebene Mitglied Zugriffsfunktion, dann ist die „FieldToString“ -Methode mit dem Ergebnis des Wandlers nennen, und gibt die resultierende Zeichenfolge.

War es hilfreich?

Lösung

Können Sie erläutern, was (wenn es regelmäßige C # war) Sie den Ausdruck auswerten möchten? Ich kann den Ausdruck leicht genug schreiben - ich einfach nicht vollständig die Frage verstehen ...

(edit re Kommentar) - in diesem Fall wird es so etwas wie:

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

Oder, wenn der Typ zu binden ablehnt, werden Sie eine Besetzung / convert injizieren müssen:

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

Andere Tipps

Sie müssen das Objekt in einem ExpressionConstant wickeln, z.B. von Expression.Constant verwenden. Hier ein Beispiel:

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();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top