Пример #1
0
        private Expression <Func <TType, IDiff, TType> > Compile()
        {
            ParameterExpression orig = Expression.Parameter(typeof(TType), "orig");
            ParameterExpression diff = Expression.Parameter(typeof(IDiff), "diff");
            ParameterExpression ret  = Expression.Parameter(typeof(TType), "ret");
            ParameterExpression item = Expression.Parameter(typeof(IDiffClassItem), "item");

            return(Expression.Lambda <Func <TType, IDiff, TType> >(
                       Expression.Block(
                           new[] { ret },
                           Expression.Assign(
                               ret,
                               Expression.New(typeof(TType))
                               ),
                           Expression.Block(Class <TType> .Properties.Select(property =>
                                                                             Expression.Assign(
                                                                                 Expression.Property(ret, property.ReflectionPropertyInfo),
                                                                                 Expression.Property(orig, property.ReflectionPropertyInfo)
                                                                                 )
                                                                             )),
                           ExpressionExtensions.ForEach(
                               item,
                               diff,
                               Expression.IfThen(
                                   Expression.Not(Expression.TypeIs(item, typeof(IDiffItemUnchanged))),
                                   Expression.Block(
                                       Expression.Switch(
                                           Expression.Property(
                                               Expression.Property(
                                                   item,
                                                   DiffItemsMembers.ClassProperty()
                                                   ),
                                               FastPropertyMembers.UniqueID()
                                               ),
                                           Expression.Throw(
                                               Expression.New(typeof(Exception))
                                               ),
                                           Class <TType> .Properties.Select(property => this.EvaluateProperty(ret, orig, property, item)).ToArray()
                                           )
                                       )
                                   )
                               ),
                           ret
                           ),
                       orig, diff
                       ));
        }
Пример #2
0
        private Expression EvaluateProperty(ParameterExpression leftEnumerator, ParameterExpression leftSomeLeft, ParameterExpression rightEnumerator, ParameterExpression rightSomeLeft, Expression conflicts, Expression ret, Property property)
        {
            Expression leftCurrent  = Expression.Property(leftEnumerator, EnumerableMembers.Current(typeof(IDiffItem)));
            Expression rightCurrent = Expression.Property(rightEnumerator, EnumerableMembers.Current(typeof(IDiffItem)));

            /* PSEUDO CODE FOR THIS:
             * if (leftSomeLeft && leftCurrent.UniqueID == ID)
             * {
             *     if (rightSomeLeft && rightCurrent.UniqueID == ID)
             *     {
             *         CheckConflicts(leftCurrent, rightCurrent)
             *         rightSomeLeft = next(rightCurrent)
             *     }
             *     else
             *         add(leftCurrent)
             *     leftSomeLeft = next(leftCurrent)
             * }
             * else if (rightSomeLeft && rightCurrent.UniqueID == ID)
             * {
             *     add(rightCurrent)
             *     rightSomeLeft = next(rightCurrent)
             * }
             */

            Expression leftShouldBeProcessed = Expression.AndAlso(
                leftSomeLeft,
                Expression.Equal(
                    Expression.Property(
                        Expression.Property(
                            Expression.Convert(
                                leftCurrent,
                                typeof(IDiffClassItem)
                                ),
                            DiffItemsMembers.ClassProperty()
                            ),
                        FastPropertyMembers.UniqueID()
                        ),
                    Expression.Constant(property.UniqueID)
                    )
                );

            Expression rightShouldBeProcessed = Expression.AndAlso(
                rightSomeLeft,
                Expression.Equal(
                    Expression.Property(
                        Expression.Property(
                            Expression.Convert(
                                rightCurrent,
                                typeof(IDiffClassItem)
                                ),
                            DiffItemsMembers.ClassProperty()
                            ),
                        FastPropertyMembers.UniqueID()
                        ),
                    Expression.Constant(property.UniqueID)
                    )
                );

            return(Expression.IfThenElse(
                       leftShouldBeProcessed,
                       Expression.Block(
                           Expression.IfThenElse(
                               rightShouldBeProcessed,
                               Expression.Block(
                                   this.CompileCheckConflicts(property, leftCurrent, rightCurrent, conflicts, ret),
                                   this.MoveEnumerator(rightEnumerator, rightSomeLeft)
                                   ),
                               Expression.Call(
                                   ret,
                                   ListMembers.Add(typeof(IDiffItem)),
                                   leftCurrent
                                   )
                               ),
                           this.MoveEnumerator(leftEnumerator, leftSomeLeft)
                           ),
                       Expression.IfThen(
                           rightShouldBeProcessed,
                           Expression.Block(
                               Expression.Call(
                                   ret,
                                   ListMembers.Add(typeof(IDiffItem)),
                                   rightCurrent
                                   ),
                               this.MoveEnumerator(rightEnumerator, rightSomeLeft)
                               )
                           )
                       ));
        }