IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Paramètres Expression Lambda


Sujet :

C#

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2012
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2012
    Messages : 5
    Points : 6
    Points
    6
    Par défaut Paramètres Expression Lambda
    Bonjour à tous,

    Je vous expose mon problème en se beau samedi ensoleillé:

    J’aimerai pour voir effectuer un tri multiple sur une liste en récupérant la sélection rentrée par l'utilisateur pour le tri ( Sélection enregistrée dans la structure Ordretri ).

    Pour le cela j'aimerais pouvoir remplacer les paramètres de mon expression lambda directement par la sélection récupérée.

    Voici un exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private void Tri_Choix_Added(OrdreTri ordreTri)
            {
    	     SortableBindingList<CAC.Business.C_Activite> List_Activite_DS = new SortableBindingList<CAC.Business.C_Activite>();
     
                 var result = List_Activite_DS
                        .OrderBy(item => item.Numero)
                        .ThenBy(item => item.nom )
                        .ThenBy(item => item.groupe);
     
                 List_Activite_DS = new SortableBindingList<C_Activite>(result.ToList());
     
    	}
    J'aimerais donc pouvoir intégrer directement ordreTri à la place de item.Numero comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
          var result = List_Activite_DS
                        .OrderBy(item => ordreTri.listCol[0])
                        .ThenBy(item => ordreTri.listCol[1] )
                        .ThenBy(item => ordreTri.listCol[2]);
    Le code compile sans erreur mais le tri ne se fait pas.


    Je vous remercie d'avance pour l'attention.
    Cordialement.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par Dynas Voir le message
    Le code compile sans erreur mais le tri ne se fait pas.
    Normal : tu tries selon quelque chose qui a la même valeur pour tous les items (quel que soit l'item, la valeur utilisée pour le tri est toujours ordreTri.listCol[x])

    En fait, il faut générer dynamiquement les expressions lambda. C'est pas très évident, mais ça se fait... Voilà une implémentation assez basique (sous forme de méthodes d'extensions) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    public static class QueryableExtensions
    {
        public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortCriteria)
        {
            return source.AddSort(sortCriteria, _orderBy);
        }
     
        public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string sortCriteria)
        {
            return source.AddSort(sortCriteria, _thenBy);
        }
     
        private static readonly MethodInfo _orderBy = typeof(Queryable)
                                .GetMethods()
                                .Where(m => m.Name == "OrderBy" && m.GetParameters().Length == 2)
                                .First();
        private static readonly MethodInfo _thenBy = typeof(Queryable)
                                .GetMethods()
                                .Where(m => m.Name == "ThenBy" && m.GetParameters().Length == 2)
                                .First();
     
        private static IOrderedQueryable<T> AddSort<T>(this IQueryable<T> source, string sortCriteria, MethodInfo orderMethod)
        {
            Type criteriaType;
            var expr = MakeSelectorExpression<T>(sortCriteria, out criteriaType);
            var realMethod = orderMethod.MakeGenericMethod(typeof(T), criteriaType);
            return (IOrderedQueryable<T>)realMethod.Invoke(null, new object[] { source, expr });
        }
     
        static LambdaExpression MakeSelectorExpression<T>(string propertyName, out Type propertyType)
        {
            var param = Expression.Parameter(typeof(T));
            var body = Expression.Property(param, propertyName);
            var expr = Expression.Lambda(body, param);
            propertyType = body.Type;
            return expr;
        }
    }
    (note : ce n'est pas très optimisé ; il faudrait faire un système de cache pour ne pas utiliser MakeGenericMethod et Invoke à chaque fois... Si tu veux une implémentation un peu plus aboutie, jette un oeil à Dynamic Linq)

    Tu peux l'utiliser comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
          var result = List_Activite_DS
                        .AsQueryable()
                        .OrderBy(ordreTri.listCol[0])
                        .ThenBy(ordreTri.listCol[1])
                        .ThenBy(ordreTri.listCol[2]);
    (note que je passe directement le nom de la propriété en paramètre, pas une expression lambda)

    Et si tu ne connais pas à l'avance le nombre de critères :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var tmp = List_Activite_DS.AsQueryable();
    foreach(var sortColumn in ordreTri.listCol)
    {
        var ordered = tmp as IOrderedQueryable<CAC.Business.C_Activite>;
        if (ordered != null)
            tmp = ordered.ThenBy(sortColumn);
        else
            tmp = tmp.OrderBy(sortColumn);
    }
    var result = tmp;
    Soit dit en passant, si tu fais le tri avec Linq, à quoi ça te sert d'utiliser SortableBindingList ? Tu pourrais gérer le tri directement avec SortableBindingList. (d'ailleurs, quelle implémentation de cette classe utilises-tu ? Ce n'est pas une classe du framework...)

Discussions similaires

  1. Réponses: 11
    Dernier message: 01/12/2011, 15h53
  2. Réponses: 2
    Dernier message: 09/08/2010, 15h41
  3. expression lambda evaluee qu'une seule fois
    Par vandamme dans le forum Boost
    Réponses: 10
    Dernier message: 17/12/2009, 14h49
  4. Décortiquer une expression lambda
    Par anthyme dans le forum Framework .NET
    Réponses: 4
    Dernier message: 17/12/2009, 12h57
  5. Réponses: 0
    Dernier message: 22/12/2008, 16h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo