Comment combiner plusieurs expressions de sélection similaires dans une seule expression?
3 Réponses :
Si tous les sélecteurs seuls em> initialize Vous aurez également besoin d'un agencydo code> Objets (comme votre exemple), vous pouvez lancer les expressions sur
nouvelle expression code>, puis Appelez
expression.new code> avec les membres
code> des expressions. P>
expressionnserviteur de code> pour remplacer le
paramètreeExpression code> S à partir des expressions d'origine avec un seul
paramètreeexpression code> pour l'expression que vous êtes créer. p>
En réalité, il est membreInitExpression code> (le
nouvelle expression code> est juste le CTOR); Cela peut être fait cependant (ajouté)
pas simple; Vous devez réécrire toutes les expressions - bien, strictement, vous pouvez recycler la plupart de l'une d'entre elles, mais le problème est que vous avez différemment x code> dans chacun (même s'il a l'air identique), d'où vous Besoin d'utiliser un visiteur pour remplacer tous les paramètres avec le final em>
x code>. Heureusement, ce n'est pas trop mauvais dans 4.0:
static Expression<Func<TSource, TDestination>> Combine<TSource, TDestination>(
params Expression<Func<TSource, TDestination>>[] selectors)
{
var param = Expression.Parameter(typeof(TSource), "x");
return Expression.Lambda<Func<TSource, TDestination>>(
Expression.MemberInit(
Expression.New(typeof(TDestination).GetConstructor(Type.EmptyTypes)),
from selector in selectors
let replace = new ParameterReplaceVisitor(
selector.Parameters[0], param)
from binding in ((MemberInitExpression)selector.Body).Bindings
.OfType<MemberAssignment>()
select Expression.Bind(binding.Member,
replace.VisitAndConvert(binding.Expression, "Combine")))
, param);
}
+1 pour écrire tout ce code. Il pourrait être beaucoup plus simple en remplaçant la boucle imbriquée avec des appels LINQ et un nouveau paramètre code>
@Slaks peut-être, peut-être. C'était déjà assez complexe mais le lecteur a probablement plus de chances de le grok dans une mise en page plus procédurale
@Slaks - Ajout, juste pour le plaisir
J'avais adapté votre code et travaille bien .. mais je ferais de travailler avec des expressions telles que l'expression
Si quelqu'un d'autre trébuche sur ceci avec un cas d'usage similaire comme le mien (mes sélectionnées ciblées différentes classes basées sur le niveau de détail nécessaire):
Scénario simplifié: P>
public static Expression<Func<Data.Blog, BlogViewModel>> Map() { return BlogSummaryViewModel.Map().Concat(i => new BlogViewModel { PostCount = i.Posts.Count() }); }
Afficher les données de la liste. Ceci est nécessaire pour éviter de charger des champs inutiles de la base de données.