Сравнение разных типов в деревьях выражений - PullRequest
1 голос
/ 07 февраля 2020

В моем API я даю возможность фильтровать результат - аналогично выражению SQL, ГДЕ. Это работает, если я использую строковое поле и сравниваю его со строковым значением:

https://apiurl/items?filterfieldname=name&filterfieldvalue=test

Теперь я получаю только те элементы, имя которых «test»

Однако, если я хочу применить это к логическому полю (в данном случае, называемому «isActive»), чтобы вернуть только активные элементы:

https://apiurl/items?filterfieldname=isActive&filterfieldvalue=true

Затем я получаю следующее исключение: System.InvalidOperationException: 'Бинарный оператор Equal не определен для типов' System.Nullable`1 [System.Boolean] 'и' System.String '.'

Я использую следующий код для создания выражения:

    static Expression<Func<T, bool>> GetExpressionForFilter<T>(string propertyName, string propertyValue)
    {
        var nameForWhereClause = propertyName.ToLowerInvariant();
        var valueForWhereClause = propertyValue.Trim().ToLowerInvariant();

        var parameterExp = Expression.Parameter(typeof(T), "type");
        var propertyExp = Expression.Property(parameterExp, nameForWhereClause);

        ConstantExpression someValue = Expression.Constant(valueForWhereClause, typeof(string));


        return Expression.Lambda<Func<T, bool>>(Expression.Equal(propertyExp, someValue), parameterExp);
    }

И применяю выражение к моей коллекции:

        var condition = GetExpressionForFilter<TEntity>(entitiesResourceParameters.FilterFieldName, entitiesResourceParameters.FilterFieldValue);
        condition.Compile();

        var collectionAfterFilter = collectionBeforeFilter.Where(condition).AsQueryable();

Я пытался преобразовать тип свойства в строку прежде чем сравнивать его со строкой «истина» или «ложь», но это не имеет значения.

Я хотел бы иметь возможность ввести любой тип поля (включая логическое) и сравнить его со значением (как строка) этого поля (например, «истина» или «ложь»). Это возможно?

1 Ответ

2 голосов
/ 07 февраля 2020

Вы можете преобразовать строковое значение в тип, с которым вы пытаетесь его сравнить.

    var propertyType = property.PropertyType;
    var value = Convert.ChangeType(valueForWhereClause, propertyType);

    ConstantExpression someValue = Expression.Constant(value, propertyType);

Помните, что Convert.ChangeType может выдать исключение, если указано недопустимое значение (например, &filterfieldvalue=foo).

...