Erweiterungsmethode, um eine Liste innerhalb eines übergeordneten Objekts zu sortieren

StackOverflow https://stackoverflow.com/questions/802789

  •  03-07-2019
  •  | 
  •  

Frage

public class Person
{
    public string name { get; set; }
    public Email email { get; set; }

}

public class Email
{
    public string desc { get; set; }
}

public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression, bool desc)
{            
    var param = Expression.Parameter(typeof(T), string.Empty);
    try
    {
        var property   = Expression.Property(param, sortExpression);
        var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);

        if (desc)
        {
            return source.AsQueryable<T>().OrderByDescending<T, object>(sortLambda);
        }

        return source.AsQueryable<T>().OrderBy<T, object>(sortLambda);
    }
    catch (ArgumentException)
    {
        return source;
    }
}

        List<Person> vet = new List<Person>();

        Person p = new Person { name = "aaa", email = new Email { desc = "bbb@aaa.com" } };
        Person pp = new Person { name = "bbb", email = new Email { desc = "aaa@aaa.com" } };
        vet.Add(p);
        vet.Add(pp);

        vet.Sort("name",true); //works
        vet.Sort("email.desc",true) // doesnt work

kann mir jemand helfen?

War es hilfreich?

Lösung

Wenn Sie diese Funktionalität Blick in einen Artikel von ScottGu auf dem dynamische Linq-Bibliothek . Ich glaube, es wird tun, was Sie wollen.

Während Lambdas sind typsicher es gibt Zeiten, wenn Sie auf dem fliegen, um die Abfrage erzeugen mögen, im Gegensatz zu jeder möglichen Kombination aufweist, die ein Benutzer zum Beispiel sortieren.

Bearbeiten

Ich reparierte Ihre Methode. Grundsätzlich benötigen Sie einen Ausdruck für jedes Mitglied Zugang zu schaffen.

 public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression, bool desc)
    {
        var param = Expression.Parameter(typeof(T), string.Empty);
        try
        {
            var fields = sortExpression.Split('.');
            Expression property = null;
            Expression parentParam = param;
            foreach (var field in fields)
            {
                property = Expression.Property(parentParam, field);
                parentParam = property;

            }

            var sortLambda = 
                Expression.Lambda<Func<T, object>>(
                  Expression.Convert(property, typeof(object)), param);

            if (desc)
            {
                return source.AsQueryable<T>().
                     OrderByDescending<T, object>(sortLambda);
            }

            return source.AsQueryable<T>().
                 OrderBy<T, object>(sortLambda);
        }
        catch (ArgumentException)
        {
            throw;
        }
    }

Andere Tipps

Vielleicht möchten Sie über eine andere Methode denken, die eine benutzerdefinierte Comparer Objekt nimmt den Vergleich zu tun. Sie könnten dann eine benutzerdefinierte Comparer Person schreiben, die sie Adressen auf der Grundlage ihrer E-Mail vergleicht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top