Я пытаюсь написать деревья выражений для динамического построения LINQ. У меня есть сетка на стороне клиента с отложенной загрузкой данных сетки на стороне сервера. Сетка запрашивает строки, которые включают модель фильтра в ресурс запроса. Данное свойство моего ресурса запроса может иметь несколько типов в зависимости от того, какой столбец фильтруется.
Я искал SO и нашел несколько похожих сообщений, но они не совсем охватывали мою точную настройку / проблемы - поскольку большинство ответов было больше сосредоточено на использовании Convert.ChangeType
или использовании dynamic
, оба из которых я уже использую.
Вот FilterModel:
public class FilterModel
{
public string Type { get; set; }
public IEnumerable<dynamic> Values { get; set; }
}
Итак Вот некоторые примеры запросов:
Фильтр по набору идентификаторов:
{
type: "set"
values: [1, 2, 3, 4]
}
Фильтр по набору категорий:
{
type: "set"
values: ["Category_1", "Category_3"]
}
где тип каждой записи в values
определяется типом свойства соответствующего столбца объекта-строки.
Ошибка и код:
Я получаю сообщение об ошибке при попытке для преобразования в тип свойства столбца объекта Row: System.InvalidCastException: Object must implement IConvertible.
Настройка:
FilterModel filter = new FilterModel() { Type = "set", Values = [1, 2, 3, 4] };
ParameterExpression rowModelParameterExpression = Expression.Parameter(typeof(RowModel));
string propertyName = "id"; // "category"
PropertyInfo property = typeof(RowModel).GetProperty(propertyName);
Type propertyType = property.PropertyType;
MemberExpression propertyExpression = Expression.Property(rowModelParameterExpression , property);
Преобразование logi c (ошибка в этом коде) :
Type listType = typeof(List<>).MakeGenericType(new[] { propertyType });
MethodInfo contains = listType.GetMethod("Contains", new[] { propertyType });
Expression comparisonValue = Expression.Constant(Convert.ChangeType(filter.Values, listType));
Expression predicateBody = Expression.Call(comparisonValue, contains, propertyExpression);