摘要:我想知道如何从表达式的主体中检测特定的定义,然后以所需的方式更改它,例如
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(...)))
作为编写清晰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&...
根据我的看法,您需要的是ExpressionVisitor
来遍历和修改ExpressionTree
。我要更改的一件事是您调用Any
的方式。代替