Lambda 表达式用于访问一个对象的属性,该属性是 C# 中另一个对象的属性

发布于 2024-11-16 01:30:26 字数 2659 浏览 6 评论 0原文

我有这两个类:

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?

I have this two classes:

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; }
//...
}

and want to dinamically filter a List of Contratos based on Contratos.entidadeFinanceira.Nome. This is part of a Method that filters the list based on a property selected by the user.

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

When the Method executes it throws an exception 'entidadeFinanceira.Nome' is not a member of type 'GAcordos.Models.Contratos' on the line

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

But if I write the expression directly:

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

it works fine.

So, how can I build the lambda expression x => x.property.property == constVal?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

红玫瑰 2024-11-23 01:30:26

简单地说,您需要使用 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 很重要,以防 constValnull;这样可以避免很多意想不到的问题)

Simply, you need two uses of PropertyOrField.

Constructed manually, x => x.Foo.Bar == constVal is:

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

(note that it is important to include constValType in case constVal is null; this avoids a lot of unexpected problems)

烟花肆意 2024-11-23 01:30:26

似乎在调用

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

Seems that when calling

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

the variable col contains "entidadeFinanceira.Nome". You may reuse all the splitting of col you did above and do something like:

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

Now the expression property should be correct and you can use it to build the body expression:

var body = Expression.Equal(
    property, 
    fixedItem, 
    false, 
    Type
        .GetType("GAcordos.Helpers.Comparators")
        .GetMethod(oper, new Type[] { propType, propType })
    );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文