[英]C# inspect and modify Expression<Func<T, bool>>?
My generic repository method is declared like this:我的通用存储库方法声明如下:
public virtual async Task<List<T>> GetMany(Expression<Func<T, bool>> filterExpression)
I would like to investigate that filterExpression
and check if T
is of a certain type AND if so, check if there's a filter for a property called ShardKey
.我想调查那个
filterExpression
并检查T
是否属于某种类型,如果是,检查是否有一个名为ShardKey
的属性的过滤器。 Also, if the type checks out but the filter is not present, I would like to add it.另外,如果类型检查出来但过滤器不存在,我想添加它。
How can I achieve this?我怎样才能做到这一点?
Using an ExpressionVisitor
you can search the Expression
tree to determine if a reference to the desired property is made.使用
ExpressionVisitor
,您可以搜索Expression
树以确定是否引用了所需的属性。 If you wanted to be more sure, you could test to see if it is in a certain type of logical test as well.如果您想更加确定,您可以测试它是否也在某种类型的逻辑测试中。
If you don't find the desired reference, you can add a parent test to the filterExpression
.如果找不到所需的引用,可以将父测试添加到
filterExpression
。
Here is an example, assuming ShardKey
is an int
:这是一个示例,假设
ShardKey
是一个int
:
public virtual async Task<List<T>> GetMany<T>(Expression<Func<T, bool>> filterExpression) {
if (typeof(T) == typeof(CertainType) && !filterExpression.ReferencesMember<CertainType>("ShardKey")) {
var skTest = Expression.Equal(Expression.PropertyOrField(filterExpression.Parameters[0], "ShardKey"), Expression.Constant(7));
filterExpression = Expression.Lambda<Func<T,bool>>(Expression.AndAlso(skTest, filterExpression.Body), filterExpression.Parameters);
}
Here is the ExpressionVisitor
implementation:这是
ExpressionVisitor
的实现:
public static class ExpressionExt {
public static bool ReferencesMember<T>(this Expression ex, string memberName) {
var mi = typeof(T).GetMember(memberName);
if (mi.Length != 1)
throw new ArgumentException($"{memberName} ambiguous or not found for {typeof(T).Name}");
var mf = new MemberFinder(mi[0]);
mf.Visit(ex);
return mf.Found;
}
class MemberFinder : ExpressionVisitor {
MemberInfo mi;
public bool Found = false;
public MemberFinder(MemberInfo _mi) => mi = _mi;
[return: NotNullIfNotNull("node")]
public override Expression Visit(Expression node) {
if (Found)
return node;
else
return base.Visit(node);
}
protected override Expression VisitMember(MemberExpression me) {
if (me.Member == mi)
Found = true;
return me;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.