Лямбда-выражение для доступа к свойству объекта, которое является свойством другого объекта в c # - PullRequest
3 голосов
/ 17 июня 2011

У меня есть два класса:

public class Contratos
{
//...
    public int EntidadeFinanceiraId { get; set; }
   [Column("Nome")]
    public EntidadesFinanceiras entidadeFinanceira { get; set; }
//...
}

public class EntidadesFinanceiras
{
    [Key]
    public int ID { get; set; }
    public string Nome { get; set; }
//...
}

и я хочу динамически фильтровать список контратов на основе Contratos.entidadeFinanceira.Nome.Это часть метода, который фильтрует список на основе свойства, выбранного пользователем.

    public IQueryable<Models.Contratos> applyLambdaFilter(string val, string col, string oper, IQueryable<Models.Contratos> contratosList)
    {
        if (!string.IsNullOrWhiteSpace(val))
        {
            string typeName;
            string columnName;
            Type propType;
            string[] propName = col.Split(new[] { '.' });
            if (propName.Count() > 1)
            {
                typeName = "GAcordos.Models." + propName[0]; //entidadeFinanceira
                columnName = propName[1]; //Nome
                propType = Type.GetType("GAcordos.Models.Contratos").GetProperty(propName[0]).PropertyType.GetProperty(columnName).PropertyType; //String
            }
            else
            {
                typeName = "GAcordos.Models.Contratos";
                columnName = propName[0]; //Other Contratos property
                propType = Type.GetType(typeName).GetProperty(columnName).PropertyType;
            }
            if (propType != null)
            {
                var fixedItem = Comparators.getFixedItemWithType(val, propType);
                var param = Expression.Parameter(typeof(GAcordos.Models.Contratos), "x");
                var body = Expression.Equal(Expression.PropertyOrField(param, col.ToString()), fixedItem, false, Type.GetType("GAcordos.Helpers.Comparators").GetMethod(oper, new Type[] { propType, propType }));
                var lambda = Expression.Lambda<Func<GAcordos.Models.Contratos, bool>>(body, param);
                contratosList = contratosList.Where(lambda.Compile()).AsQueryable();
            }
        }
        return contratosList;
    }

Когда метод выполняется, он генерирует исключение 'entidadeFinanceira.Nome' не является членом типа'GAcordos.Models.Contratos' в строке

var body = Expression.Equal(Expression.PropertyOrField(param, col.ToString()), fixedItem, false, Type.GetType("GAcordos.Helpers.Comparators").GetMethod(oper, new Type[] { propType, propType }));

Но если я напишу выражение напрямую:

contratosList = contratosList.Where(x => x.entidadeFinanceira.Nome == val);

, оно будет работать нормально.

ТакКак я могу построить лямбда-выражение x => x.property.property == constVal?

Ответы [ 2 ]

5 голосов
/ 17 июня 2011

Просто вам нужно два варианта использования PropertyOrField.

Построен вручную, x => x.Foo.Bar == constVal - это:

var param = Expression.Parameter(typeof(ObjectType), "x");
var lambda = Expression.Lambda<Func<ObjectType, bool>>(
    Expression.Equal(
        Expression.PropertyOrField(
           Expression.PropertyOrField(param, "Foo"), "Bar"
        ), Expression.Constant(constVal, constValType)
    ), param);

(обратите внимание, что важно включить constValType в случае, если constVal равно null; это позволяет избежать множества неожиданных проблем)

0 голосов
/ 17 июня 2011

Кажется, что при вызове

Expression.PropertyOrField(param, col.ToString())

переменная col содержит "entidadeFinanceira.Nome".Вы можете повторно использовать все разбиения col, которые вы делали выше, и сделать что-то вроде:

Expression property = param;
foreach(var pName in propName) { 
    property = Expression.PropertyOrField(property, pName);
}

Теперь выражение property должно быть правильным, и вы можете использовать его для построения выражения body:

var body = Expression.Equal(
    property, 
    fixedItem, 
    false, 
    Type
        .GetType("GAcordos.Helpers.Comparators")
        .GetMethod(oper, new Type[] { propType, propType })
    );
...