Давайте предположим, что нам нужно запросить список объектов, и мы не знаем критериев, который является довольно динамичным, и у объекта есть и словари, и простые поля внутри. Пусть это будет следующий объект - Адрес (я оставил только один свойство для простоты).
public class Address
{
#region Public members
/// <summary>
/// The extra datafield values
/// </summary>
public IDictionary<string, string> DataFieldValues { get; set; }
public string City { get; set; }
#endregion
}
Теперь, если мы запросим фиксированное поле с именем Город , когда я получу реализацию:
private static Expression<Func<Address, bool>> BuildLambdaForAQueryItem(string caption, string value)
{
ParameterExpression param = Expression.Parameter(typeof(Address), caption);
BinaryExpression body = Expression.Equal(Expression.PropertyOrField(param, caption),
Expression.Constant(value,
typeof(Address).GetProperty(
caption).PropertyType));
return Expression.Lambda<Func<Address, bool>>(body, param);
}
Теперь, если я хочу запросить на DataFieldValue выборку, мне тоже нужно написать лямбда-аналог:
x => x.DataFieldValues.ContatinsKey (ключ) && DataFieldValues [ключ] == значение
То, что я получаю с помощью метода, приведенного ниже, почти похоже , но все равно оно не применяет фильтр правильно:
private static Expression<Func<Address, bool>> BuildLambdaForAnExtraField(PostedQueryItem queryItem)
{
ParameterExpression dataFields = Expression.Parameter(typeof(Address), "x");
var dictionaryExpression = Expression.PropertyOrField(dataFields, "DataFieldValues");
var keyExists = Expression.Call(dictionaryExpression, "ContainsKey", null, Expression.Constant(queryItem.Caption));
Expression dictionaryAccessExpr = Expression.Property(dictionaryExpression, "Item",
Expression.Constant(queryItem.Caption));
var valueCorresponds = Expression.Equal(dictionaryAccessExpr, Expression.Constant(queryItem.Value));
return Expression.Lambda<Func<Address, bool>>(keyExists, dataFields).And(
Expression.Lambda<Func<Address, bool>>(valueCorresponds, dataFields));
}