我有一个与以下代码相关的问题;基本上我想创建一个动态 LINQ 表达式,它允许我在基于字符串的 LINQ 中创建 Select 语句:
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;
您可以通过像这样转换绑定(bind)来轻松解决此问题:
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。
关于c# - Expression.MemberInit -- 最佳重载方法匹配有一些无效参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24959506/