10
votes

Combinez plusieurs expressions de sélection similaires dans une seule expression

Comment combiner plusieurs expressions de sélection similaires dans une seule expression? XXX


1 commentaires

Afficher les données de la liste. Ceci est nécessaire pour éviter de charger des champs inutiles de la base de données.


3 Réponses :


1
votes

Si tous les sélecteurs seuls initialize agencydo Objets (comme votre exemple), vous pouvez lancer les expressions sur nouvelle expression , puis Appelez expression.new avec les membres des expressions.

Vous aurez également besoin d'un expressionnserviteur pour remplacer le paramètreeExpression S à partir des expressions d'origine avec un seul paramètreeexpression pour l'expression que vous êtes créer.


1 commentaires

En réalité, il est membreInitExpression (le nouvelle expression est juste le CTOR); Cela peut être fait cependant (ajouté)



19
votes

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);        
}


4 commentaires

+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


@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 > sélecteur1 = x => nouveau {nom = x.name}; Au lieu de l'expression > Selector1 = x => nouvelle agenceDTo {nom = x.name}; Comment puis-je le faire fonctionner avec de tels types anonymes? Ce sélecteur d'expression (membre des membres ).Body se casse si des types anonymes sont utilisés



1
votes

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()
        });
    }


0 commentaires