简体   繁体   English

C# 检查和修改表达式<func<t, bool> >? </func<t,>

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM