La mia soluzione:
public static Func<Student, object> BuildPredicate(string propertyName)
{
Type studentType = typeof(Student);
ParameterExpression studentParam = Expression.Parameter(studentType, "x");
MemberInfo ageProperty = studentType.GetProperty(propertyName);
MemberExpression valueInNameProperty = Expression.MakeMemberAccess(studentParam, ageProperty);
UnaryExpression expression = Expression.Convert(valueInNameProperty, typeof (object));
Expression<Func<Student, object>> orderByExpression = Expression.Lambda<Func<Student, object>>(expression, studentParam);
return orderByExpression.Compile();
}
nella tua espressione rendere il codice viene aggiunto casting per object
.
Ecco come è possibile creare una catena di ThenBy
:
var sortedStudents = students.OrderBy(BuildPredicate("Age"));
foreach (var property in typeof(Student).GetProperties().Where(x => !String.Equals(x.Name, "Age")))
{
sortedStudents = sortedStudents.ThenBy(BuildPredicate(property.Name));
}
var result = sortedStudents.ToList();
Infine, classe Student
campione:
public class Student
{
public int Age { get; set; }
public string Name { get; set; }
}
Aggiornamento:
Un altro approccio sta usando gli attributi per contrassegnare offerte dal tuo Student
per usarli in OrderBy
e ThenBy
. Come:
public class Student
{
[UseInOrderBy]
public int Age { get; set; }
[UseInOrderBy(Order = 1)]
public string Name { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
internal class UseInOrderByAttribute : Attribute
{
public int Order { get; set; }
}
Ecco come si può costruire la catena di ordinamento utilizzando UseInOrderByAttribute
:
Type studentType = typeof (Student);
var properties = studentType.GetProperties()
.Select(x => new { Property = x, OrderAttribute = x.GetCustomAttribute<UseInOrderByAttribute>() })
.Where(x => x.OrderAttribute != null)
.OrderBy(x => x.OrderAttribute.Order);
var orderByProperty = properties.FirstOrDefault(x => x.OrderAttribute.Order == 0);
if (orderByProperty == null)
throw new Exception("");
var sortedStudents = students.OrderBy(BuildPredicate(orderByProperty.Property.Name));
foreach (var property in properties.Where(x => x.Property.Name != orderByProperty.Property.Name))
{
sortedStudents = sortedStudents.ThenBy(BuildPredicate(property.Property.Name));
}
var result = sortedStudents.ToList();
Fix: BuildPredicate
può essere Scritto senza dynamic
. BuildPredicate
codice di esempio modificato.
fonte
2013-01-12 13:53:56
Per chiarire: stai cercando un modo per creare una singola espressione che puoi trasmettere a .OrderBy che replicherà la funzionalità di passare una serie di espressioni a .OrderBy e .ThenBy, co rRect? –
Dupe http://stackoverflow.com/questions/41244/dynamic-linq-orderby – aquinas