У меня есть вопрос, связанный со следующим кодом; в основном я хочу создать динамическое выражение 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);
Это ошибка:
Компилятор задает проблему с Microsoft FW 3.5; с FW 4.0 или выше у меня нет проблем. Но мне нужно скомпилировать проект в 3.5. Кто-нибудь знает обходное решение этой проблемы?
У вас проблема с изменением. Переменная 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.
Select<string, MemberBinding>