Question

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?

Was it helpful?

Solution

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();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top