Créer une action <T> pour &quot;définir&quot; une propriété lorsque l&#39;expression LINQ est fournie, ainsi

c# expression-trees

Question

J'aimerais pouvoir générer une expression compilée pour définir une propriété, étant donné l'expression lambda qui fournit la méthode "get" pour une propriété.

Voici ce que je recherche:

public Action<int> CreateSetter<T>(Expression<Func<T, int>> getter)
{
    // returns a compiled action using the details of the getter expression tree, or null
    // if the write property is not defined.
}

J'essaie toujours de comprendre les différents types de classes d'expression, alors si vous pouviez me diriger dans la bonne direction, ce serait formidable.

Réponse acceptée

En utilisant la réponse de @Ani comme point de départ, vous pouvez utiliser ce qui suit pour générer une expression compilée .

[TestMethod]
public void CreateSetterFromGetter()
{
    Action<Person, int> ageSetter = InitializeSet((Person p) => p.Age);
    Action<Person, string> nameSetter = InitializeSet((Person p) => p.Name);

    Person p1 = new Person();
    ageSetter(p1, 29);
    nameSetter(p1, "John");

    Assert.IsTrue(p1.Name == "John");
    Assert.IsTrue(p1.Age == 29);
}

public class Person { public int Age { get; set; } public string Name { get; set; } }

public static Action<TContainer, TProperty> InitializeSet<TContainer, TProperty>(Expression<Func<TContainer, TProperty>> getter)
{
    PropertyInfo propertyInfo = (getter.Body as MemberExpression).Member as PropertyInfo;

    ParameterExpression instance = Expression.Parameter(typeof(TContainer), "instance");
    ParameterExpression parameter = Expression.Parameter(typeof(TProperty), "param");

    return Expression.Lambda<Action<TContainer, TProperty>>(
        Expression.Call(instance, propertyInfo.GetSetMethod(), parameter),
        new ParameterExpression[] { instance, parameter }).Compile();
}

Vous devez mettre en cache l’expression compilée pour la conserver à des fins multiples.


Réponse d'expert

Je crains seulement les pointeurs (je ne suis pas à un ordinateur) - mais;

  • lambda's .Body sera très probablement MemberExpression
  • faire une distribution sécurisée ( as etc.) et accéder au .Member
  • puisque vous pensez que c'est une propriété, cela devrait être un PropertyInfo, donc testez / diffusez, etc.
  • à partir d'un PropertyInfo, appelez GetSetMethod () pour obtenir le MethodInfo correspondant
  • utilisez Delegate.CreateDelegate pour obtenir cela en tant que délégué (en passant le type d'action)
  • enfin, transformez le délégué retourné dans le type de délégué attendu



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