Имеется следующий класс:
public class ExportItem
{
public Dictionary<string, object> Container { get; set; }
public ExportItem()
{
Container = new Dictionary<string, object>();
}
}
Контейнер в данном случае содержит пары ключ (название свойства) - значение этого свойства (числа, строки и перечисления, при необходимости буду делать нужный каст).
Соответственно, имеется список подобных объектов, который нужно отфильтровать по стандартным выражениям (равно, не равно, больше, меньше, больше или равно, меньше или равно, начинается с).
Как поступить в случае с обычным классом, в котором свойства - это свойства, а не ключи словаря, я примерно представляю (хотя так глубоко с лямбда-выражениями раньше работать не приходилось).
var parameter = Expression.Parameter(typeof(People), property);
var member = Expression.Property(parameter, "Id"); //x.Id
var constant = Expression.Constant(3);
var body = Expression.GreaterThanOrEqual(member, constant); //x.Id >= 3
var finalExpression = Expression.Lambda<Func<People, bool>>(body, parameter); //x => x.Id >= 3
Вот только как приспособить этот пример для решения задачи со словарём? Возможно, есть иные способы построения и реализации фильтра для подобной структуры данных. Изменять её, к сожалению, нельзя - объект, содержащий словарь, должен таким и остаться.
Пытался использовать что-то вроде:
var parameter = Expression.Parameter(typeof(ExportItem), property);
var member = Expression.Property(parameter, "Container['Id']"); //x.Container['Id']
var constant = Expression.Constant("12");
var body = Expression.GreaterThanOrEqual(member, constant); //x.Container['Id'] >= "12"
var finalExpression = Expression.Lambda<Func<ExportItem, bool>>(body, parameter); //x => x.Container['Id'] >= "12"
Но предсказуемо ничего не вышло. Названия свойств и их значения, само собой, будут меняться. То есть, нужно что-то вроде настраиваемого:
return exportItems.Where(c =>
int.Parse(c.Container[conditions[0]].ToString()) >= int.Parse(values[0]) &&
int.Parse(c.Container[conditions[1]].ToString()) != int.Parse(values[1]))
.ToList();
Условий может быть не более двух, типы - int, float, enum, string
, ну да это уже отдельный вопрос - если что, сделаю условиями, что-то вроде если число, то больше или равно использовать можно, а если строка - то нет.
UPD: работаем под .NET 3.5
Для обращения по индексу в словаре используется свойство Item
. Это стандартное имя свойства индексатора.
Для вызова индексатора в выражениях есть специальная перегрузка, принимающая в дополнение список параметров для индексатора.
В итоге выражение
c.Container[param]
можно собрать так:
var parameter = Expression.Parameter(typeof(ExportItem), property); // c
var container = Expression.Property(parameter, "Container"); //c.Container
var indexer = Expression.Property(container, "Item", Expression.Constant("12")); //c.Container['12']
для более старой версии framework можно воспользоваться тем, что свойства представляют из себя пару методов set_*
и get_*
. Таким образом для получения значения нужен метод get_Item
, который нужно вызвать с переданными параметрами
var parameter = Expression.Parameter(typeof(ExportItem), property); // c
var container = Expression.Property(parameter, "Container"); //c.Container
var getProp = container.Type.GetMethod("get_Item");
var indexer = Expression.Call(container, getProp, Expression.Constant("12"));
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Проблема следующая мы создаем матрицу, задаем размерностьДальше считаем суммы каждой строки
Как на wpf реализовать выделение и перемещение выбранной области на канвасе, и если есть несколько вариантов - какой быстрее
Почему расшифровка не поддерживает латиницу? Пробовал разные методы добавления Encoding не помогло (
Нужно реализовать функционал редактирования текста на С# как в графических редакторах, например paintУ пользователя возможность перемещать...