Func <> attribue une valeur au résultat

c# expression-trees lambda

Question

Ce que j'essaie de faire semble simple, mais je ne trouve pas de solution. Supposons que j'ai une méthode avec cette signature:

public void Foo<T,K>(Expression<Func<T,K>> binding, T item, K value)

Ce que je veux faire dans ma méthode est le suivant: appliquer l'élément Func à l'élément, obtenir la propriété de type K sur laquelle pointe l'expression de liaison, et lui affecter une "valeur".

Si l'expression de liaison est quelque chose comme:

public void Foo<T,K>(Expression<Func<T,K>> binding, T item, K value)

Où "c" est "T" et "Propriété" est "K", je peux facilement utiliser une réflexion et définir la valeur à l'aide de FieldInfo. Le code suivant fonctionne:

public void Foo<T,K>(Expression<Func<T,K>> binding, T item, K value)

Mais l'expression pourrait être quelque chose comme ceci:

public void Foo<T,K>(Expression<Func<T,K>> binding, T item, K value)

ou

public void Foo<T,K>(Expression<Func<T,K>> binding, T item, K value)

Dans ce cas, le code de réflexion ne fonctionne pas, car "Property" n'appartient pas directement à T, mais reste une expression lambda valide pour la signature de la méthode.

Je sais que si je compile le Func et que je l'exécute sur mon élément de type TI, j'obtiens la propriété, mais c'est comme une "copie" de celle-ci, et non une référence, donc même si je lui affecte la valeur, la propriété sur l'article original ne soit pas changé.

Si quelqu'un a une solution claire à ce problème, ou s'il m'indique simplement quelque chose qui peut me permettre de mieux connaître Expression Trees, vous êtes le bienvenu.

Réponse acceptée

On dirait que vous ne voulez pas vraiment un «K» d'un T, mais que vous voulez plutôt affecter un K à un K que T connaît, n'est-ce pas?

public void Foo<T,K>(Action<T,K> binding, T item, K value)
{
    binding(item, value);
}

Cela semble plus correct car la liaison est un délégué qui peut prendre un T et dire à T de faire ce qu'il faut avec un K, n'est-ce pas? Appelez ça comme ça?

public void Foo<T,K>(Action<T,K> binding, T item, K value)
{
    binding(item, value);
}

Réponse populaire

static void AssignValue<TSource, TResult>(Expression<Func<TSource, TResult>> expression, TSource source, TResult result)
{
    var paramExp = expression.Parameters.Single();
    var assignExp = Expression.Assign(expression.Body, Expression.Constant(result));
    var lambdaExp = Expression.Lambda(assignExp, paramExp);
    lambdaExp.Compile().DynamicInvoke(source);
}

Usage:

static void AssignValue<TSource, TResult>(Expression<Func<TSource, TResult>> expression, TSource source, TResult result)
{
    var paramExp = expression.Parameters.Single();
    var assignExp = Expression.Assign(expression.Body, Expression.Constant(result));
    var lambdaExp = Expression.Lambda(assignExp, paramExp);
    lambdaExp.Compile().DynamicInvoke(source);
}



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi