MiBol
MiBol

Reputation: 2125

Expression.MemberInit -- The best overloaded method match has some invalid arguments

I have a question related with the following code; basically I want to create a dynamically LINQ expression that allows me to create a Select sentence in LINQ based in a string:

public class SelectBuilder<T, T>
{
    Func<T, T> CreateNewStatement(string fields)
    {
        // input parameter "o"
        var xParameter = Expression.Parameter(typeof(T), "o");

        // new statement "new Data()"
        var xNew = Expression.New(typeof(T));

        // create initializers
        var bindings = fields.Split(',').Select(o => o.Trim())
            .Select(o =>
            {

                // property "Field1"
                var mi = typeof(T).GetProperty(o);

                // original value "o.Field1"
                var xOriginal = Expression.Property(xParameter, mi);

                // set value "Field1 = o.Field1"
                return Expression.Bind(mi, xOriginal);
            }
        );

        // initialization "new Data { Field1 = o.Field1, Field2 = o.Field2 }"
        var xInit = Expression.MemberInit(xNew, bindings); // <-- Error on this line

        // expression "o => new Data { Field1 = o.Field1, Field2 = o.Field2 }"
        var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);

        // compile to Func<Data, Data>
        return lambda.Compile();
    }
}

This is the LINQ expression:

var vLINQ = (from a in PrimaryTable.AsEnumerable()
                                 join b in vDTsec.AsEnumerable()
                                 on a.Field<Object>("ID") equals b.Field<Object>("ID")
                                 into Group
                                 from q in Group.DefaultIfEmpty()
                                 select q).Select(MYSELECTSTRING);

This is the error: Error

The compiler gives a problem with the Microsoft FW 3.5; with the FW 4.0 or above I don't have problems. But I need to compile the project in 3.5. Anybody knows a workaround to this problem?

Upvotes: 2

Views: 1708

Answers (1)

vcsjones
vcsjones

Reputation: 141668

You are having a problem with variance. Your bindings variable is an IEnumerable<MemberAssignment> where MemberInit is expecting IEnumerable<MemberBinding>. Since T is covariant in IEnumerable<out T> in .NET 4.0, it works fine. To illustrate the problem a little more, what is happening is this:

IEnumerable<MemberBinding> foo = bindings;

You can easily fix this by casting your bindings like so:

var bindings = fields.Split(',').Select(o => o.Trim())
            .Select(o =>
            {

                // property "Field1"
                var mi = typeof(TA).GetProperty(o);

                // original value "o.Field1"
                var xOriginal = Expression.Property(xParameter, mi);

                // set value "Field1 = o.Field1"
                return (MemberBinding)Expression.Bind(mi, xOriginal);
            }
        );

This will always work since MemberAssignment derives from MemberBinding.

Upvotes: 4

Related Questions