I'm trying to build a method that can capture assignments from a strongly-typed statement body. The method call should look something like this:
myObject.Assign(o =>
{
o.SomeProperty = 1;
o.AnotherProperty = "two";
});
I'd like to get a list of assignments; an array of MemberAssignment
instances seems fitting.
It's unclear to me what the method header of Assign()
needs to look like.
Here's what I currently have:
public class MyClass
{
public void Assign(System.Linq.Expressions.Expression<System.Action<MyBunchOfProps>> assignments)
{
}
}
public struct MyBunchOfProps
{
public int SomeProperty { get; set; }
public string AnotherProperty { get; set; }
}
With a statement body and multiple assignments, I get "A lambda expression with a statement body cannot be converted to an expression tree".
If I omit the statement body and only do one assignment (myObject.Assign(o => o.SomeProperty = 1);
), I instead get "An expression tree may not contain an assignment operator".
Do I need to use a different class rather than Expression
?
It would be easy to analyze an expression-tree containing a bunch of assignments, but unfortunately, C# doesn't support the creation of expression-trees with assignments or statements through lambdas yet, as the compiler errors indicate.
I suggest you construct a custom object that can hold a list of (member access lambda, object) tuples and use that instead.
For example, you should be able to create a class that would allow for this syntax:
var list = new AssignmentList<MyBunchOfProps>
{
{ o => o.SomeProperty, 1 },
{ o => o.AnotherProperty, "two" }
};
Here's an example implementation for this:
public class AssignmentList<T> : IEnumerable<Tuple<LambdaExpression, object>>
{
private readonly List<Tuple<LambdaExpression, object>> _list
= new List<Tuple<LambdaExpression, object>>();
public void Add<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)
{
_list.Add(Tuple.Create<LambdaExpression, object>(selector, value));
}
public IEnumerator<Tuple<LambdaExpression, object>> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}