【问题标题】:getting at a deep property for a lambda Expression获取 lambda 表达式的深层属性
【发布时间】:2012-03-09 13:46:32
【问题描述】:

我有一些代码:

CaseHeaderComparer CaseComparer = new CaseHeaderComparer();
List<CaseHeader> CasesToProcess = new List<CaseHeader>();

foreach (GroupField fld in Fields)
{
    //get the field property - ie. Division
    System.Reflection.PropertyInfo piField = typeof(CaseHeader).GetProperty(fld.GroupFieldType.PropertyName);
    //get the item property - ie. DivisionID
    System.Reflection.PropertyInfo piItem = piField.PropertyType.GetProperty(fld.GroupFieldType.ValueMember);

    foreach (CaseHeader ch in ToProcess)
    {
        object chItem = piField.GetValue(ch, null);
        Guid ItemID = chItem != null ? (Guid)piItem.GetValue(chItem, null) : Guid.Empty;

        if (fld.Items.Select(i => i.ItemID).Contains(ItemID))
        {
            CasesToProcess.Add(ch);
        }
    }
    ToProcess = ToProcess.Except(CasesToProcess, CaseComparer).ToList();
}

我想转换成使用 linq 和 lambdas - 我昨天从这里得到了一些帮助:

List<CaseHeader> ToProcess = ....;
CaseHeaderComparer CaseComparer = new CaseHeaderComparer();
IEnumerable<CaseHeader> CasesToProcess = new BackingSheetCaseHeader[] { };
foreach (GroupField fld in Fields)
{
    //get the field property - ie. Division
    System.Reflection.PropertyInfo piField = typeof(CaseHeader).GetProperty(fld.GroupFieldType.PropertyName);
    //get the item property - ie. DivisionID
    System.Reflection.PropertyInfo piItem = piField.PropertyType.GetProperty(fld.GroupFieldType.ValueMember);

    CasesToProcess.Union(
        ToProcess
            .Where(c => fld.Items.Select(i => i.ItemID)
                .Contains((piField.GetValue(c, null) != null ? (Guid)piItem.GetValue(piField.GetValue(c, null), null) : Guid.Empty)))
                , CaseComparer);
}

这行得通,但有人指出我可以按照这个思路做一些事情..

var hdr = typeof(CaseHeader);
var param = Expression.Parameter(hdr);
var cond = Expression.Condition(
    Expression.NotEqual(param, Expression.Constant(null, hdr))
,   Expression.Property(param, fld.GroupFieldType.PropertyName) <<-- but this needs to go 2 deep.. as above the item property..
,   Expression.Constant(Guid.Empty)
);
var lambda = (Func<MyCaseObj,Guid>)Expression.Lambda(cond, param).Compile();

那我就可以了

var CasesToProcess = (from csh in CasesInGroup 
    where lambda(csh).In(fld.Items.Select(i => i.ItemID)) 
    select csh);

但是 2 深位难倒我 如上所述,我需要获取 CaseHeader 的 fld.GroupFieldType.PropertyName 属性的 fld.GroupFieldType.ValueMember 属性。 第一层的值可能为空..

谁能给我一些指导,或者在某个地方阅读一下这个

谢谢

【问题讨论】:

    标签: linq reflection lambda


    【解决方案1】:

    您可能根本不需要手动构建Expression 。 C# 编译器可以将 lambda 表达式转换为 Func&lt;&gt;s Expression&lt;Func&lt;&gt;&gt;s。以下两项工作:

            var func = (Func<int, bool>)(i => i == 2);
            var expression = (Expression<Func<int, bool>>)(i => i == 2);
    

    之后expression.Compile()Func&lt;int,bool&gt;,其行为与func 相同!所以试试吧

    var expression = (Expression<Func<MyCaseObj,Guid>>)
        (c => fld.Items.Select(i => i.ItemID)
              .Contains((piField.GetValue(c, null) != null 
                         ? (Guid)piItem.GetValue(piField.GetValue(c, null), null) 
                         : Guid.Empty))
        );
    

    然后从那里拿走。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-06
      • 1970-01-01
      • 1970-01-01
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多