C # Превращение магической строки в лямбда-выражение
У меня есть набор методов расширения, которые позволяют использовать магические строки в LINQOrderBy()
методы. Я знаю, что первый вопрос будет, почему, но он является частью общего репозитория и предназначен для гибкости, чтобы строки можно было отправлять из пользовательского интерфейса и использовать напрямую.
У меня это работает, если вы передаете волшебную строку, которая представляет свойство основной сущности, к которой вы обращаетесь, но у меня возникают проблемы, делая ее более общей, чтобы она могла обрабатывать несколько уровней глубокой магической строки. Например:
IQueryable<Contact> contacts = GetContacts();
contacts.OrderByProperty("Name"); // works great
// can't figure out how to handle this
contacts.OrderByProperty("ContactType.Name");
Вот код, который у меня есть:
public static class LinqHelpers
{
private static readonly MethodInfo OrderByMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "OrderBy" && method.GetParameters().Length == 2);
private static readonly MethodInfo OrderByDescendingMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "OrderByDescending" && method.GetParameters().Length == 2);
private static readonly MethodInfo ThenByMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "ThenBy" && method.GetParameters().Length == 2);
private static readonly MethodInfo ThenByDescendingMethod = typeof(Queryable).GetMethods().Single(method => method.Name == "ThenByDescending" && method.GetParameters().Length == 2);
public static IOrderedQueryable<TSource> ApplyOrdering<TSource>(IQueryable<TSource> source, string propertyName, MethodInfo orderingMethod)
{
var parameter = Expression.Parameter(typeof(TSource), "x");
var orderByProperty = Expression.Property(parameter, propertyName);
var lambda = Expression.Lambda(orderByProperty, new[] { parameter });
var genericMethod = orderingMethod.MakeGenericMethod(new[] { typeof(TSource), orderByProperty.Type });
return (IOrderedQueryable<TSource>)genericMethod.Invoke(null, new object[] { source, lambda });
}
public static IOrderedQueryable<TSource> OrderByProperty<TSource>(this IQueryable<TSource> source, string propertyName)
{
return ApplyOrdering(source, propertyName, OrderByMethod);
}
public static IOrderedQueryable<TSource> OrderByDescendingProperty<TSource>(this IQueryable<TSource> source, string propertyName)
{
return ApplyOrdering(source, propertyName, OrderByDescendingMethod);
}
public static IOrderedQueryable<TSource> ThenByProperty<TSource>(this IOrderedQueryable<TSource> source, string propertyName)
{
return ApplyOrdering(source, propertyName, ThenByMethod);
}
public static IOrderedQueryable<TSource> ThenByDescendingProperty<TSource>(this IOrderedQueryable<TSource> source, string propertyName)
{
return ApplyOrdering(source, propertyName, ThenByDescendingMethod);
}
}
Я уверен, что мне нужно разделитьpropertyName
на период, а затем использовать эти части, чтобы создать более сложное выражение, которое включает в себяMemberExpression
а потом собственность, но я борюсь. Любая помощь или указание в правильном направлении будет принята с благодарностью.