正文表达式的复杂编辑 >

问题描述 投票:1回答:1

摘要:我想知道如何从表达式的主体中检测特定的定义,然后以所需的方式更改它,例如

e.Entity.ListA.Union(e.ListB).Any(...)...

收件人

e.Entity != null && 
((e.Entity.ListA != null && e.Entity.ListA.Any(...)) 
|| (e.Entity.ListB != null && e.Entity.ListB.Any(...)))

我认为仅使用Linq Expression技术是理想的解决方案

作为编写清晰C#代码的一部分,我编写了一组预定义的表达式,并使用LinqKit扩展名(可以在它们之间进行组合),因此它将扩展编写复杂表达式的动态性,直到一切正常为止。另外,我想用它们来过滤IQuerable和IEnumerable情况。但是,如您所知,在某些情况下,在前者或后者中定义的表达式不起作用,我成功地避免了很多此类问题。直到我提出解决方案的情况下,但我仍然觉得这并不理想。

[我将首先展示问题,然后解释所希望的解决方案,最后,我将分享我的尝试。

//---
public class AssignmentsEx : BaseEx
{ 


//.........

/// <summary>
/// (e.FreeRoles AND e.RoleClass.Roles) ⊆ ass.AllRoles
/// </summary>
public static Expression<Func<T, bool>> RolesInclosedBy<T>(IAssignedInstitution assignedInstitution) where T : class, IAssignedInstitution
    {
        var allStaticRoles = AppRolesStaticData.AdminRolesStr.GetAll();
        var assAllRoles = assignedInstitution.AllRoles.Select(s => s.Name).ToList();
        var hasAllRoles = allStaticRoles.All(assR => assAllRoles.Any(sR => sR == assR));

        if (hasAllRoles)
            return e => true;

// for LINQ to SQL the expression works perfectly as you know 
// the expression will be translated to an SQL code
// for IEnumerable case the nested object Roles with throw null obj ref 
// exception if the RoleClass is null (and this is a healthy case from code execution
// 
       return Expression<Func<T, bool>> whenToEntity = e => e.FreeRoles.Union(e.RoleClass.Roles).All(eR => assAllRoles.Any(assR => assR == eR.Name));
    }

//.........

}

如您所见,如果我使用此方法定义RoleClass为null或FreeRoles为null的对象的列表,它将抛出NullException。

-我认为最好的建议将取决于三个因素:

  • 从表达体中检测所需片段的可能性

  • 将片段修改为IEnumerable情况所需,反之亦然

  • 重建并返回新表达式

这样可以帮助我保持静态方法并通过扩展方法对其进行修改:例如例如:WithSplittedUnion()

而不是传统方式,即我现在按照以下方式使用

public class AssignmentsEx
{

public LinqExpressionPurpose purpose{get;}

public AssignmentsEx(LinqExpressionPurpose purpose) : base(purpose)
    {
          Purpose = purpose
    }

 public Expression<Func<T, bool>> RolesInclosedBy<T>(IAssignedInstitution assignedInstitution) where T : class, IAssignedInstitution
    {
        var allStaticRoles = AppRolesStaticData.AdminRolesStr.GetAll();
        var assAllRoles = assignedInstitution.AllRoles.Select(s => s.Name).ToList();
        var hasAllRoles = allStaticRoles.All(assR => assAllRoles.Any(sR => sR == assR));

        if (hasAllRoles)
            return e => true;

        Expression<Func<T, bool>> whenToObject = e => (e.FreeRoles == null || e.FreeRoles.All(eR => assAllRoles.Any(assR => assR == eR.Name)))
        && (e.RoleClass == null || e.RoleClass.Roles == null || e.RoleClass.Roles.All(eR => assAllRoles.Any(assR => assR == eR.Name)));

        Expression<Func<T, bool>> whenToEntity = e => e.FreeRoles.Union(e.RoleClass.Roles).All(eR => assAllRoles.Any(assR => assR == eR.Name));

        return Purpose switch
        {
            LinqExpressionPurpose.ToEntity => whenToEntity,
            LinqExpressionPurpose.ToObject => whenToObject,
            _ => null,
        };
    }
}

我希望解释清楚,谢谢。]

摘要:我想知道如何从表达式的主体中检测特定的定义,然后以所需的方式更改它,例如e.Entity.ListA.Union(e.ListB).Any(...)。给e.Entity!= null&...

c# entity-framework linq entity-framework-core expression-trees
1个回答
0
投票

根据我的看法,您需要的是ExpressionVisitor来遍历和修改ExpressionTree。我要更改的一件事是您调用Any的方式。代替

© www.soinside.com 2019 - 2024. All rights reserved.