Используйте string.Compare(a, b) в выражении
Со вчерашнего дня я обучаю себя деревьям выражений, и у меня возникают проблемы при сравнении двух строковых значений. Я сделал этот контрольный пример, который завершается с ошибкой:
No method 'Compare' on type 'System.String' is compatible with the supplied arguments.
Сбой во время выполнения на left = Expression.Call(
Type type = typeof(string);
Expression left, right;
left = Expression.Constant("1", type);
right = Expression.Constant("2", type);
// fails at run-time on the next statement
left = Expression.Call(
typeof(string),
"Compare",
new Type[] { type, type },
new Expression[] { left, right });
right = Expression.Constant(0, typeof(int));
Я буду использовать полученный левый и правый в Expression.Equal, LessThan, LessThanOrEqual, GreaterThan or GreaterThanOrEqual
, В этом причина метода сравнения.
Я уверен, что это что-то простое, и я свел свой код к этому простому тестовому примеру. Кто-нибудь видит, где я ошибся?
2 ответа
Это проблема в вашем Expression.Call
код:
new Type[] { type, type },
Вот пытаюсь позвонить string.Compare<string, string>
- это общие аргументы, а не типы нормальных параметров. Учитывая, что это не универсальный метод, просто используйте ноль здесь.
Короткая, но полная программа:
using System;
using System.Linq.Expressions;
class Test
{
static void Main()
{
var left = Expression.Constant("1", typeof(string));
var right = Expression.Constant("2", typeof(string));
var compare = Expression.Call(typeof(string),
"Compare",
null,
new[] { left, right });
var compiled = Expression.Lambda<Func<int>>(compare).Compile();
Console.WriteLine(compiled());
}
}
Я пытался сделать то же самое, что и предложение лямбда-где (LINQ to SQL), и, поскольку различные поиски высадили меня на этой странице, я поделюсь таким решением здесь на тот случай, если оно поможет другим, кто приземлится здесь.
Это проще всего, когда вы упрощаете то, что делаете, с помощью общего выражения сравнения.
public static Expression CompareLessThanOrEqualTo(Expression e1, Expression e2)
{
var compare = Expression.Call(typeof(string),
"Compare",
null,
new[] { e1, e2 });
return Expression.LessThanOrEqual(compare, Expression.Constant(0));
}
Тогда вы можете использовать это выражение, как и любой другой
public static Expression<Func<TypeOfParent, bool>> PropertyLessThanOrEqualString<TypeOfParent, String>(PropertyInfo property, String value)
{
var parent = Expression.Parameter(typeof(TypeOfParent));
var expressionBody = CompareLessThanOrEqualTo(Expression.Property(parent, property), Expression.Constant(value));
return Expression.Lambda<Func<TypeOfParent, bool>>(expressionBody, parent);
}
Ведьма может быть использована, например,
public static IQueryable<T> ApplyFilters<T>(this IQueryable<T> query, List<GridFilters> gridFilters)
{
// foreach filter
// Get property (propertyInfo)
// Get Value(s)
// Apply Filter
query = query.Where(PropertyLessThanOrEqualString<T, string>(propertyInfo, value1));
// ...
return query;
}
Это полезно, если у вас есть список фильтров, выбранных пользователем, которые необходимо применить, где можно выбрать значения и операторы. (Начинается с, содержит, между диапазонами)