10
votes

Accédez à des propriétés imbriquées avec Lambda dynamique à l'aide de Linq.Expression

supposons que j'ai deux classes: xxx

Ces classes sont plus ou moins données, elles sont mappées via NHibernate pour être honnête :)

dans une grille ( Datatables.net comme base) Je souhaite avoir un tri indépendant de type.

Par conséquent, j'ai créé une expression lambda: xxx

si je passe la personne comme type T et remplacez la "propriété à trier" avec "nom" Ça fonctionne bien (crée une lambda correcte) . Si la propriété de tri est "adresse.street", il ne fonctionnera pas, jette-moi l'erreur suivante: xxx

Je ne vois qu'une solution jusqu'à présent, mais pas assez clairement ... J'essaierais de scinder la chaîne qui contient le nom de la propriété (Split by.)

Quelqu'un peut-il donner une meilleure solution? Je dois ajouter la solution Extrait à un objet iquéry Query.orderby (Sortexpression) .

Je ne sais pas si mon titre est clair, allez-y et corrigez-le.

Merci d'avance.


0 commentaires

4 Réponses :


2
votes

Il me semble que vous essayez de réécrire Microsoft DynamicQuery . Pourquoi pas simplement l'utiliser à la place?

Voici un exemple: P>

IQueryable<Foo> myQuery = GetHibernateQuery();
myQuery = myQuery.OrderBy("address.street");


3 commentaires

Parce que je reçois seulement un objet iquérisable qui contient déjà un tas de données, alors j'ajoute la pagination et ainsi de suite, puis je charge que les données laissées dans la requête. Ceci est fait par NHibernate. Seulement pour le tri ne peut pas être la solution (j'espère)


C'est mon point. DynamicQuery peut déjà faire cela "Ajouter le tri à un requérant existant". J'ai une solution de démonstration sur mon blog qui fait exactement cela. blogs.teamb.com/craigstzz/2009/04/27/38243


J'ai ajouté un exemple trivial au poste.



13
votes

Qu'est-ce qui n'est pas clair?

Vous devez le diviser, puis utiliser: xxx


2 commentaires

uhm et comment feriez-vous cela si peut-être y a-t-il quelque chose comme person.company.address.street ? Je ne sais tout simplement pas comment "nich" .. ou s'il y a d'autres façons, comme Craig posté ...


Expression.property (expression.property (expression.property (expression.property (param, "personne"), "Société"), "Adresse"), "Street") La boucle simple fonctionnera.



5
votes

Voici une version plus générique de la réponse de Lukled: xxx

Vous pouvez l'utiliser comme ceci: xxx


3 commentaires

C'est une méthode excellente et réutilisable pour résoudre ce problème. Merci.


Excellente réponse +1. Vous pouvez le faire dans une doublure: renvoyer la propriétéName.split ('.'). Agrégat (expression, (corps, membre) => expression.propertyorfield (corps, membre); .


Si vous n'aimez pas que vous n'aimez pas la fantaisie, une version plus lisible utilise une version plus lisible utilise foreach , comme: corps d'expression = expression; foreach (membre var inactename.split ('.')) {corps = expression.propertyorfield (corps, membre); } retour corps;



0
votes

Essayez celui-ci

    public static IQueryable<T> SortIQueryable<T>(IQueryable<T> data, string fieldName, string sortOrder)
    {
        if (string.IsNullOrWhiteSpace(fieldName)) return data;
        if (string.IsNullOrWhiteSpace(sortOrder)) return data;

        var param = Expression.Parameter(typeof(T), "i");

        MemberExpression property = null;
        string[] fieldNames = fieldName.Split('.');
        foreach (string filed in fieldNames)
        {
            if (property == null)
            {
                property = Expression.Property(param, filed);
            }
            else
            {
                property = Expression.Property(property, filed);
            }
        }

        Expression conversion = Expression.Convert(property, typeof(object));//Expression.Property(param, fieldName)
        var mySortExpression = Expression.Lambda<Func<T, object>>(conversion, param);

        return (sortOrder == "desc") ? data.OrderByDescending(mySortExpression)
            : data.OrderBy(mySortExpression);
    }


0 commentaires