Erstellen Sie eine Aktion <T> um eine Eigenschaft zu &quot;setzen&quot;, wenn mir der LINQ-Ausdruck für das &quot;get&quot; zur Verfügung gestellt wird

c# expression-trees

Frage

Ich möchte in der Lage sein, einen kompilierten Ausdruck zu generieren, um eine Eigenschaft festzulegen, wenn der Lambda-Ausdruck angegeben wird, der die "get" -Methode für eine Eigenschaft bereitstellt.

Hier ist was ich suche:

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.
}

Ich versuche immer noch, die verschiedenen Arten von Ausdrucksklassen zu verstehen, also wenn du mich in die richtige Richtung lenken kannst, wäre das großartig.

Akzeptierte Antwort

Wenn Sie @ Anis Antwort als Ausgangspunkt verwenden, können Sie mit dem folgenden Befehl einen kompilierten Ausdruck generieren.

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

Sie sollten den kompilierten Ausdruck zwischenspeichern, um ihn für mehrere Zwecke verfügbar zu halten.


Expertenantwort

Zeiger nur fürchte ich (ich bin nicht an einem PC) - aber;

  • Das .body des Lambdas wird höchstwahrscheinlich MemberExpression sein
  • Mach einen sicheren Cast ( as etc) und .Member auf die .Member
  • Da Sie diese Eigenschaft für eine Eigenschaft halten, sollte dies eine PropertyInfo sein, also test / cast etc
  • Rufen Sie GetSetMethod () von einer PropertyInfo auf, um die entsprechende MethodInfo abzurufen
  • Verwenden Sie Delegate.CreateDelegate, um das als Delegat zu erhalten (den Aktionstyp übergeben)
  • Schreiben Sie schließlich den zurückgegebenen Delegate auf den erwarteten Delegattyp



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum