Étant donné deux expressions « sélecteur », vous avez à prendre les fixations de leur MemberInitExpression
et de créer une nouvelle expression en utilisant toutes les liaisons. Mais cette expression ne va pas fonctionner, car elle utilise deux expressions de paramètres différentes pour un seul paramètre. Nous devons régler cela aussi.
... Compte tenu
Expression<Func<TSource, TResult>> left = ... // columns
Expression<Func<TSource, TResult>> right = ... // more columns
... prendre les fixations ...
var leftInit = left.Body as MemberInitExpression;
var rightInit = right.Body as MemberInitExpression;
var bindings = leftInit.Bindings.Concat(rightInit.Bindings);
... créer une nouvelle expression ...
var result = Expression.Lambda<Func<TSource, TResult>>(
Expression.MemberInit(Expression.New(typeof(TResult)), bindings), ???);
.. .BUT, besoin de paramètre unique ...
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...
Et, en remplaçant les paramètres fonctionne bien en utilisant un visiteur d'expression:
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);
}
}
Abstracting ce genre de choses plomberie fonctionne très bien. En fait, vous pouvez simplement utiliser un existing library (spoiler: Je suis l'auteur), ce qui devrait conduire à quelque chose comme ça:
var merged = columns.Apply(moreColumns);
http://stackoverflow.com/questions/16516971/linq-dynamic-select –
Qu'est-ce qui ne va pas avec 'columns = d => {var c = columns(); c.OtherProperty = d.OtherProperty; retour c; } '? S'il vous plaît être plus précis sur ce que vous avez essayé, et ce que vous avez des problèmes spécifiques. Votre question est très large en ce moment. –
Vous ne pensez pas que je l'ai déjà fait? On dirait que vous n'avez pas testé cela parce que vous obtenez cette erreur. 'Une expression lambda avec un corps d'instruction ne peut pas être convertie en un arbre d'expression –