Lesen von Eigenschaften eines Objekts mit Ausdrucksbäumen

.net c# expression-trees lambda

Frage

Ich möchte einen Lambda-Ausdruck für jede Eigenschaft eines Objekts erstellen, der den Wert dynamisch liest.

Was ich bisher habe:

var properties = typeof (TType).GetProperties().Where(p => p.CanRead);

foreach (var propertyInfo in properties)
{
    var getterMethodInfo = propertyInfo.GetGetMethod();

    var entity = Expression.Parameter(typeof (TType));

    var getterCall = Expression.Call(entity, getterMethodInfo);

    var lambda = Expression.Lambda(getterCall, entity);
    var expression = (Expression<Func<TType, "TypeOfProperty">>) lambda;
    var functionThatGetsValue = expression.Compile();
}

Der Code funktioniert gut, wenn ich functionThatGetsValue aufruft, solange "TypeOfProperty" fest codiert ist. Ich weiß, dass ich die "TypeOfProperty" nicht dynamisch weitergeben kann. Was kann ich tun, um mein Ziel zu erreichen?

Akzeptierte Antwort

Unter der Annahme , dass Sie glücklich sind mit einem Func<TType, object> Delegierte (gemäß den obigen Ausführungen ), können Sie Expression.Convert zu erreichen , dass:

var properties = typeof(TType).GetProperties().Where(p => p.CanRead);

foreach (var propertyInfo in properties)
{
    MethodInfo getterMethodInfo = propertyInfo.GetGetMethod();
    ParameterExpression entity = Expression.Parameter(typeof(TType));
    MethodCallExpression getterCall = Expression.Call(entity, getterMethodInfo);

    UnaryExpression castToObject = Expression.Convert(getterCall, typeof(object));
    LambdaExpression lambda = Expression.Lambda(castToObject, entity);

    var functionThatGetsValue = (Func<TType, object>)lambda.Compile();
}

Beliebte Antwort

Nach Stunden des Googelns fand die Antwort hier . Ich habe die Snippets aus dem Blogeintrag hinzugefügt, da dies anderen helfen könnte, die gleichen Probleme zu haben:

public static class PropertyInfoExtensions
{
    public static Func<T, object> GetValueGetter<T>(this PropertyInfo propertyInfo)
    {
        if (typeof(T) != propertyInfo.DeclaringType)
        {
            throw new ArgumentException();
        }

        var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
        var property = Expression.Property(instance, propertyInfo);
        var convert = Expression.TypeAs(property, typeof(object));
        return (Func<T, object>)Expression.Lambda(convert, instance).Compile();
    }

    public static Action<T, object> GetValueSetter<T>(this PropertyInfo propertyInfo)
    {
        if (typeof(T) != propertyInfo.DeclaringType)
        {
            throw new ArgumentException();
        }

        var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
        var argument = Expression.Parameter(typeof(object), "a");
        var setterCall = Expression.Call(
            instance,
            propertyInfo.GetSetMethod(),
            Expression.Convert(argument, propertyInfo.PropertyType));
        return (Action<T, object>)Expression.Lambda(setterCall, instance, argument).Compile();
    }
}


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow