Some changes to the object model for 7.2

We try to avoid making changes to the object model that Reflector exposes. Doing so requires our users to make changes to their applications forcing them to recompile. However, for 7.2 we decided that a change was the right thing to do in one particular small area of the object model.

The problem of the existing model was that it didn’t handle the difference between the two LINQ queries in the following code.

            var testData = new[]
                               {
                                   new Tuple<string,string>(“b”, “1”),
                                   new Tuple<string,string>(“a”, “3”),
                                   new Tuple<string,string>(“a”, “2”),
                               };

 

            var result =
                from datum in testData
                orderby datum.Item1
                orderby datum.Item2
                select datum;

 

            foreach(var item in result)
            {
                Console.WriteLine(item);
            }

 

            var result2 =
                from datum in testData
                orderby datum.Item1, datum.Item2
                select datum;

 

            foreach (var item in result2)
            {
                Console.WriteLine(item);
            }

 

Running the above code prints out the following results, which highlight the difference between multiple orderby clauses and a single orderby clause with multiple items.

(b, 1)
(a, 2)
(a, 3)
(a, 2)
(a, 3)
(b, 1)

The old Reflector object model couldn’t express the latter type of LINQ clauses, which were instead incorrectly represented as multiple orderby clauses. The IObjectClause had the following form, making it possible only to have a group of one item.

       public interface IOrderClause : IQueryClause
       {
              IExpression Expression { get; set; }
              OrderDirection Direction { get; set; }
       }

 

For 7.2 we experimented in one of the EAPs with adding a IThenOrderClause to express subsequent expressions that happen as part of the main sort. That would reflect the way 
           orderby A,B
is translated by the compiler into
            Enumerable.ThenBy(Enumerable.OrderBy(source, filter on A), filter on B).

 

However in the end we felt that since a ThenBy needs to follow an OrderBy, it was better to have just a single node type to express the entire part of the LINQ expression. With that in mind, we have now changed the IOrderClause interface to

 

       public interface IOrderClause : IQueryClause
       {
        IExpressionAndDirectionCollection ExpressionAndDirections { get; }
       }

This exposes a collection in the standard Reflector pattern leading to the individual items.

    public interface IExpressionAndDirectionCollection : ICollection
    {
        void Clear();
        void Add(IExpressionAndDirection value);
        void AddRange(ICollection value);
        void Remove(IExpressionAndDirection value);
        void Insert(int index, IExpressionAndDirection value);
        void RemoveAt(int index);
        bool Contains(IExpressionAndDirection value);
        int IndexOf(IExpressionAndDirection value);
        IExpressionAndDirection this[int index] { get; set; }
    }

 

    public interface IExpressionAndDirection
    {
        IExpression Expression { get; set; }
        OrderDirection Direction { get; set; }
    }
 

As usual, we welcome any feedback on the change we have made. 

Leave a Reply

Your email address will not be published. Required fields are marked *