How to parse OData $filter with regular expression in C#?

前端 未结 3 1778
误落风尘
误落风尘 2020-12-05 05:47

Hi I\'m wondering what the best approach would be to parse an OData $filter string in C#, for example

/API/organisations?$filter=\"name eq \'Facebook\' or name eq \'

3条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-05 06:03

    I think you are supposed to travserse the AST with the interface provided using the visitor pattern.

    Consider you have this class that represents a filter

    public class FilterValue
    {
        public string ComparisonOperator { get; set; }
        public string Value { get; set; }
        public string FieldName { get; set; }
        public string LogicalOperator { get; set; }
    }
    

    So, how do we "extract" the filters that comes with the OData parameters to your class?

    Well the FilterClause object have an Expression property which is a SingleValueNode wich inherits from a QueryNode. The QueryNode have the Accept method who takes a QueryNodeVisitor.

        public virtual T Accept(QueryNodeVisitor visitor);
    

    Right, so you must implement your own QueryNodeVisitor and do your stuff. Below is a non finished example (I dont override all possible visitors).

    public class MyVisitor : QueryNodeVisitor
        where TSource: class
    { 
        List filterValueList = new List();
        FilterValue current = new FilterValue();
        public override TSource Visit(BinaryOperatorNode nodeIn)
        {
            if(nodeIn.OperatorKind == Microsoft.Data.OData.Query.BinaryOperatorKind.And 
                || nodeIn.OperatorKind == Microsoft.Data.OData.Query.BinaryOperatorKind.Or)
            {
                current.LogicalOperator = nodeIn.OperatorKind.ToString();
            }
            else
            {
                current.ComparisonOperator = nodeIn.OperatorKind.ToString();
            }
            nodeIn.Right.Accept(this);
            nodeIn.Left.Accept(this);
            return null;
        }
        public override TSource Visit(SingleValuePropertyAccessNode nodeIn)
        {
            current.FieldName = nodeIn.Property.Name;
            //We are finished, add current to collection.
            filterValueList.Add(current);
            //Reset current
            current = new FilterValue();
            return null;
        }
    
        public override TSource Visit(ConstantNode nodeIn)
        {
            current.Value = nodeIn.LiteralText;
            return null;
        }
    
    }
    

    Then, fire away :)

    MyVisitor visitor = new MyVisitor();
    options.Filter.FilterClause.Expression.Accept(visitor);
    
    
    

    When it has traversed the tree your

    visitor.filterValueList
    

    should contain the filters in your desired format. Im sure more work is needed but if you can get this rolling I think you can figure it out.

    提交回复
    热议问题