Get all 'where' calls using ExpressionVisi

2019-01-24 20:51发布

问题:

I have a query, like such:

var query = from sessions in dataSet
                    where (names.Contains(sessions.Username))
                    where (sessions.Login.TimeOfAction == dt)                    
                    select new {    sessions.Username, 
                                    sessions.Login, 
                                    sessions.Logout, sessions.Duration };

I want to implement an ExpressionVisitor to extract BOTH the where clauses as Lambda's, but so far have only been able to get the first using a class called 'InnermostWhereFinder' that comes from the MSDN tutorial on a custom query provider for the TerraServer web-service.

It is:

internal class InnermostWhereFinder : ExpressionVisitor
    {
        private MethodCallExpression innermostWhereExpression;

        public MethodCallExpression GetInnermostWhere(Expression expression)
        {
            Visit(expression); 
            return innermostWhereExpression;
        }

        protected override Expression VisitMethodCall(MethodCallExpression expression)
        {
            if (expression.Method.Name == "Where")
                innermostWhereExpression = expression;

            Visit(expression.Arguments[0]);

            return expression;
        }
    }

Ive tried tweaking this class heavily to return both where clauses with no success. Couldn't find any great documentation on this, can anyone help? This will ultimately need to result in multiple LambdaExpression objects I can work with, I think.

回答1:

Use the class found here http://msdn.microsoft.com/en-us/library/bb882521%28v=vs.90%29.aspx as your base. You can then create your Visitor like this

internal class WhereFinder : ExpressionVisitor
    {
        private IList<MethodCallExpression> whereExpressions = new List<MethodCallExpression>();

        public IList<MethodCallExpression> GetWhere(Expression expression)
        {
            Visit(expression); 
            return whereExpressions;
        }

        protected override Expression VisitMethodCall(MethodCallExpression expression)
        {
            if (expression.Method.Name == "Where")
                whereExpressions.Add(expression);

            Visit(expression.Arguments[0]);

            return expression;
        }
    }