質問
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
誰か助けてくれますか?
解決
この機能が必要な場合は、動的Linqライブラリ。私はそれがあなたが望むことをするだろうと信じています。
Lambdaはタイプセーフですが、たとえばユーザーが並べ替えることができるすべての組み合わせを持つのではなく、オンザフライでクエリを生成したい場合があります。
編集
メソッドを修正しました。基本的に、メンバーアクセスごとに式を作成する必要があります。
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;
}
}
他のヒント
カスタムComparerオブジェクトを使用して比較を行う別のメソッドを検討することもできます。次に、メールアドレスに基づいてそれらを比較するPersonのカスタムComparerを作成できます。
所属していません StackOverflow