考える二つの「セレクタ」の表現は、あなたが彼らのMemberInitExpression
からバインディングを取り、すべてのバインディングを使用して、新しい式を作成しました。しかし、この式は1つのパラメータに対して2つの異なるパラメータ式を使用するため、動作しません。私たちもそれを修正する必要があります。考える
...
Expression<Func<TSource, TResult>> left = ... // columns
Expression<Func<TSource, TResult>> right = ... // more columns
...バインディングを取る...
var leftInit = left.Body as MemberInitExpression;
var rightInit = right.Body as MemberInitExpression;
var bindings = leftInit.Bindings.Concat(rightInit.Bindings);
...新しい式を作成...
var result = Expression.Lambda<Func<TSource, TResult>>(
Expression.MemberInit(Expression.New(typeof(TResult)), bindings), ???);
..しかし、単一のパラメータが必要です...
var binder = new ParameterBinder(left.Parameters[0], right.Parameters[0]);
var bindings = binder.Visit(leftInit.Bindings.Concat(rightInit.Bindings));
// now, just use right.Parameters[0] as parameter...
そして、パラメータを交換すると表現の訪問者を使用してうまく機能:この配管のものを抽象化
class ParameterBinder : ExpressionVisitor
{
readonly ParameterExpression parameter;
readonly Expression replacement;
public ParameterBinder(ParameterExpression parameter, Expression replacement)
{
this.parameter = parameter;
this.replacement = replacement;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == parameter)
return replacement;
return base.VisitParameter(node);
}
}
はかなりうまく動作します。 、そのようなことにつながるはずです。
var merged = columns.Apply(moreColumns);
http://stackoverflow.com/questions/16516971/linq-dynamic-select:実際には、あなただけのexisting library(私が作者だスポイラー)を使用することができます –
'columns = d => {var c = columns();の何が問題なのですか。 c.OtherProperty = d.OtherProperty;戻り値c; } '?あなたが試したこと、そしてあなたが何か問題を抱えていることについてもっと具体的にしてください。あなたの質問は現時点では非常に広いです。 –
私はすでにそれをしたとは思わない?このエラーが発生したため、テストしなかったようです。 '文の本文を持つラムダ式は式ツリーに変換できません ' –