Expression.MemberInit - лучшее совпадение перегруженного метода имеет недопустимые аргументы

1

У меня есть вопрос, связанный со следующим кодом; в основном я хочу создать динамическое выражение LINQ, которое позволяет мне создать предложение Select в LINQ, основанное на строке:

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

Это выражение LINQ:

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);

Это ошибка: Изображение 174551

Компилятор задает проблему с Microsoft FW 3.5; с FW 4.0 или выше у меня нет проблем. Но мне нужно скомпилировать проект в 3.5. Кто-нибудь знает обходное решение этой проблемы?

Теги:
linq

1 ответ

2
Лучший ответ

У вас проблема с изменением. Переменная bindings - это IEnumerable<MemberAssignment> где MemberInit ожидает IEnumerable<MemberBinding>. Так как T ковариантно в IEnumerable<out T> в.NET 4.0, он отлично работает. Чтобы проиллюстрировать проблему немного больше, что происходит:

IEnumerable<MemberBinding> foo = bindings;

Вы можете легко исправить это, добавив свои привязки так:

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

Это всегда будет работать, поскольку MemberAssignment происходит от MemberBinding.

  • 0
    Вот, пожалуйста! ... отлично !, Большое спасибо. Работает восхитительно.
  • 0
    Мы также можем принудительно вызвать тип возврата методов LINQ, указав аргументы типа, например Select<string, MemberBinding>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню