Oppositional
Oppositional

Reputation: 11211

Structure for serializing logical expressions

I need to pass a list of logical expressions to a WCF service, something along the following:

[0] (A & B) || (C & D)
[1] (E || F)
[2] G

The above is an example list of three elements, with each element describing a boolean expression that contains AND, OR and grouping. The items in the conditions (A,B,C,D,E,F,G) will all be the same type of entity.

Is the best approach to just use strings, and parse them on the server when the message is received, or is there a class structure/hierarchy I might be able to use? I have difficulty thinking of how to model the grouping and boolean conditions as a class structure.

The real world goal is to model a multi-level list of users that will be approving or rejecting a published document. When the condition expressed by the first element in the list is satisfied, the users in the next level will be notified that their input is needed. This continues until all conditions have been evaluated.

Upvotes: 1

Views: 1099

Answers (1)

carlosfigueira
carlosfigueira

Reputation: 87308

Both options (using strings and a data structure) work fine - it will just depend where you want to have to convert the expressions into strings to transfer over the wire (which may lead to a smaller message size) or transfer the data structure directly (the wire size may be larger, but you'll share the same expression tree between the client and server).

The code below shows one possible data structure for the examples you have - a tree (it's currently binary but it doesn't have to be).

public class StackOverflow_6915554
{
    [DataContract]
    [KnownType(typeof(LeafExpression))]
    [KnownType(typeof(BinaryExpression))]
    public class Expression
    {
    }

    [DataContract]
    public class LeafExpression : Expression
    {
        [DataMember]
        public string Name;
    }

    [DataContract]
    public class BinaryExpression : Expression
    {
        [DataMember]
        public BinaryOperator Operator;
        [DataMember]
        public Expression Left;
        [DataMember]
        public Expression Right;
    }

    public enum BinaryOperator
    {
        And,
        Or,
    }

    public static void Test()
    {
        List<Expression> expressions = new List<Expression>();
        expressions.Add(new BinaryExpression
        {
            Left = new BinaryExpression
            {
                Left = new LeafExpression { Name = "A" },
                Operator = BinaryOperator.And,
                Right = new LeafExpression { Name = "B" },
            },
            Operator = BinaryOperator.Or,
            Right = new BinaryExpression
            {
                Left = new LeafExpression { Name = "C" },
                Operator = BinaryOperator.And,
                Right = new LeafExpression { Name = "D" },
            }
        });

        expressions.Add(new BinaryExpression
        {
            Left = new LeafExpression { Name = "E" },
            Operator = BinaryOperator.Or,
            Right = new LeafExpression { Name = "F" }
        });

        expressions.Add(new LeafExpression { Name = "G" });

        XmlWriterSettings ws = new XmlWriterSettings
        {
            Indent = true,
            IndentChars = "  ",
            Encoding = new UTF8Encoding(false),
            OmitXmlDeclaration = true,
        };

        MemoryStream ms = new MemoryStream();
        XmlWriter w = XmlWriter.Create(ms, ws);

        DataContractSerializer dcs = new DataContractSerializer(typeof(List<Expression>));
        dcs.WriteObject(w, expressions);
        w.Flush();

        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    }
}

Upvotes: 1

Related Questions