H. Я пытаюсь создать запрос linq, который динамически генерирует запрос для пользовательского заказа для динамически отправляемого поля.
Я строительная логика
Expression<Func<string, int>> SpaceStringSortExpression = (a) => a.StartsWith(" ") ? 2 : 1;
Подпись этого кода (SpaceStringSortExpression.ToString ()) имеет вид "a => IIF (a.StartsWith (\" \ "), 2, 1)"
Чтобы сделать это динамически, я сделал:
ParameterExpression parameter = Expression.Parameter(typeof(TSource), "p1");
Expression orderByProperty = Expression.Property(parameter, propertyName);
ConstantExpression c = Expression.Constant(" ", typeof(string));
MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
Expression call = Expression.Call(orderByProperty, mi, c);
Expression<Func<TSource, bool>> lambda = Expression.Lambda<Func<TSource, bool>>(call, parameter);
ConditionalExpression t = Expression.IfThenElse(call, Expression.Constant(2), Expression.Constant(1));
//t.tostring() - IIF(p1.Login.StartsWith(" "), 2, 1)
LambdaExpression callt = Expression.Lambda(t, new[] { parameter });
//callt.tostring() = p1 => IIF(p1.Login.StartsWith(" "), 2, 1)
Но я не могу заставить его работать, передавая результат в OrderBy
MethodInfo genericMethod;
genericMethod = OrderByMethod.MakeGenericMethod
genericMethod = OrderByDescendingMethod.MakeGenericMethod
(new[] { typeof(TSource), typeof(Int32) });
object ret = genericMethod.Invoke(null, new object[] { source, callt });
return (IQueryable<TSource>)ret;
А у меня есть (перевод с локализованного IIS)
Unable to convert "System.Linq.Expressions.Expression`1[System.Action`1[XXXX.User]]" to type "System.Linq.Expressions.Expression`1[System.Func`2[XXXX.User,System.Int32]]".
Весь код:
public static IQueryable<TSource> OrderByPropertyRegardingWhiteSpaces<TSource>
(this IQueryable<TSource> source, string propertyName, bool ascDirection = true)
{
ParameterExpression parameter = Expression.Parameter(typeof(TSource), "p1");
Expression orderByProperty = Expression.Property(parameter, propertyName);
ConstantExpression c = Expression.Constant(" ", typeof(string));
MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
Expression call = Expression.Call(orderByProperty, mi, c);
Expression<Func<TSource, bool>> lambda = Expression.Lambda<Func<TSource, bool>>(call, parameter);
ConditionalExpression t = Expression.IfThenElse(call, Expression.Constant(2), Expression.Constant(1));
//t.tostring() - IIF(p1.Login.StartsWith(" "), 2, 1)
LambdaExpression callt = Expression.Lambda(t, new[] { parameter });
//callt.tostring() = p1 => IIF(p1.Login.StartsWith(" "), 2, 1)
MethodInfo genericMethod;
genericMethod = OrderByMethod.MakeGenericMethod
(new[] { typeof(TSource), typeof(Int32) });
object ret = genericMethod.Invoke(null, new object[] { source, callt });
return (IQueryable<TSource>)ret;
}
private static readonly MethodInfo OrderByMethod =
typeof(Queryable).GetMethods()
.Where(method => method.Name == "OrderBy")
.Where(method => method.GetParameters().Length == 2)
.Single();
Может ли кто-нибудь помочь мне с этим?
более простой пример (просто сортировка по динамическому параметру) работает нормально:
public static IQueryable<TSource> OrderByProperty<TSource>
(this IQueryable<TSource> source, string propertyName, bool ascDirection = true)
{
ParameterExpression parameter = Expression.Parameter(typeof(TSource), "p1");
Expression orderByProperty = Expression.Property(parameter, propertyName);
LambdaExpression call = Expression.Lambda(orderByProperty, new[] { parameter });
MethodInfo genericMethod;
if (ascDirection)
{
genericMethod = OrderByMethod.MakeGenericMethod
(new[] { typeof(TSource), orderByProperty.Type });
}
else
{
genericMethod = OrderByDescendingMethod.MakeGenericMethod
(new[] { typeof(TSource), orderByProperty.Type });
}
object ret = genericMethod.Invoke(null, new object[] { source, call });
return (IQueryable<TSource>)ret;
}