У меня есть список объектов, которые я хочу фильтровать с помощью выражения, которое создается во время выполнения. Окончательное выражение содержит несколько условий, в сочетании с && или ||, заключенными в предложения. Каждое условие выглядит следующим образом:
x => x.ValueType == 1 && x.Value == "abc"
Как вы можете видеть, есть только 2 свойства для проверки. Если ValueType
равен 1, Value
всегда является строкой. Если ValueType
равно 2, Value
всегда должно содержать строку, которая может быть преобразована в double.
Value
имеет тип string. Если условие использует оператор больше, чем (>), Value
нужно преобразовать в double. Поэтому в этом случае тело выражения выглядит так:
$x.ValueType == 2 & .Call System.Convert.ToDouble($x.Value) > 5
Пока здесь, все работает как ожидалось.
Проблема:
Если я использую выражение выше (ValueType == 2 && Value> 5) с этим списком:
var list = new List<Item>();
list.Add(new Item { ValueType = 1, Value = "abc" });
list.Add(new Item { ValueType = 1, Value = "def" });
list.Add(new Item { ValueType = 2, Value = "25" });
list.Add(new Item { ValueType = 2, Value = "37" });
var results = list.AsQueryable().Where(expression);
Я получаю FormatException: строка ввода не была в правильном формате. Я думал, что он не будет пытаться преобразовать элементы 1 и 2 в double, потому что условие ValueType уже возвращает false. Но я был неправ.
Должен ли я использовать TryParse
все эти значения, прежде чем преобразовывать их в double, или использовать свойства для каждого типа значений вместо одного свойства string? Я попытался вставить TryParse
в дерево выражений, но я не знаю, как...
Изменение объектной модели на несколько свойств вызовет много изменений, поэтому я хочу избежать этого "решения".
Я уверен, кто-то здесь знает, как справиться с этой проблемой. Или, по крайней мере, может указать мне в правильном направлении.
Используйте &&
вместо &
для оценки короткого замыкания на С#.
void Main()
{
Func<Item, bool> expression = x => x.ValueType == 2 && Convert.ToDouble(x.Value) > 5;
var list = new List<Item>();
list.Add(new Item { ValueType = 1, Value = "abc" });
list.Add(new Item { ValueType = 1, Value = "def" });
list.Add(new Item { ValueType = 2, Value = "25" });
list.Add(new Item { ValueType = 2, Value = "37" });
var results = list.AsQueryable().Where(expression);
results.Dump();
}
public class Item
{
public int ValueType {get;set;}
public string Value {get;set;}
}