【问题标题】:Lambda expression to access a property of an object that is property of another object in c#Lambda表达式访问一个对象的属性,该属性是c#中另一个对象的属性
【发布时间】:2011-06-17 10:34:34
【问题描述】:

我有这两个类:

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 动态过滤一个 Contratos 列表。这是根据用户选择的属性过滤列表的方法的一部分。

    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' is not a member of type '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);

效果很好。

那么,如何构建 lambda 表达式 x => x.property.property == constVal?

【问题讨论】:

    标签: c# lambda expression


    【解决方案1】:

    简单地说,你需要PropertyOrField 的两次使用。

    手动构造,x =&gt; 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);
    

    (请注意,如果constValnull,请务必包含constValType;这样可以避免很多意外问题)

    【讨论】:

    • (注意我在掩饰 captured constVal 和显式 constant... 之间的区别...但是:嗯)跨度>
    • 让我开心!非常感谢!
    【解决方案2】:

    好像打电话的时候

    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 })
        );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多