Пример #1
0
        private MethodCallExpression NewDiffReplaced(ParameterExpression ret, Property property, ParameterExpression @base, ParameterExpression changed)
        {
            MemberExpression baseProperty    = Expression.Property(@base, property.ReflectionPropertyInfo);
            MemberExpression changedProperty = Expression.Property(changed, property.ReflectionPropertyInfo);

            return(Expression.Call(
                       ret,
                       ListMembers.Add(typeof(IDiffItem)),
                       Expression.New(
                           DiffItemsMembers.NewClassReplaced(property.Type),
                           Expression.Constant(property),
                           baseProperty,
                           changedProperty
                           )
                       ));
        }
Пример #2
0
        private Expression NewDiffChanged(ParameterExpression ret, Property property, ParameterExpression @base, ParameterExpression changed)
        {
            IDiffAlgorithm diff = this.aMergerImplementation.Partial.Algorithms.GetDiffAlgorithm(property.Type);

            if (diff.IsDirect)
            {
                return(this.NewDiffReplaced(ret, property, @base, changed));
            }

            MemberExpression baseProperty    = Expression.Property(@base, property.ReflectionPropertyInfo);
            MemberExpression changedProperty = Expression.Property(changed, property.ReflectionPropertyInfo);

            ParameterExpression tmp = Expression.Parameter(typeof(IDiff <>).MakeGenericType(property.Type), "tmp");

            return(Expression.Block(
                       new[] { tmp },
                       Expression.Assign(
                           tmp,
                           Expression.Call(
                               Expression.Constant(diff),
                               DiffAlgorithmMembers.Compute(property.Type),
                               baseProperty,
                               changedProperty
                               )
                           ),
                       Expression.IfThenElse(
                           Expression.NotEqual(
                               Expression.Property(tmp, DiffMembers.Count()),
                               Expression.Constant(0)
                               ),
                           Expression.Call(
                               ret,
                               ListMembers.Add(typeof(IDiffItem)),
                               Expression.New(
                                   DiffItemsMembers.NewClassChanged(property.Type),
                                   Expression.Constant(property),
                                   tmp
                                   )
                               ),
                           this.NewDiffUnchanged(ret, property, @base)
                           )
                       ));
        }
Пример #3
0
        private Expression NewDiffUnchanged(ParameterExpression ret, Property property, ParameterExpression value)
        {
            if (!this.aAlwaysIncludedProperties.Contains(property))
            {
                return(Expression.Empty());
            }

            MemberExpression valueProperty = Expression.Property(value, property.ReflectionPropertyInfo);

            return(Expression.Call(
                       ret,
                       ListMembers.Add(typeof(IDiffItem)),
                       Expression.New(
                           DiffItemsMembers.NewClassUnchanged(property.Type),
                           Expression.Constant(property),
                           valueProperty
                           )
                       ));
        }
Пример #4
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)
                               )
                           )
                       ));
        }
Пример #5
0
        private Expression CompileCheckConflicts(Property property, Expression leftCurrent, Expression rightCurrent, Expression conflicts, Expression ret)
        {
            /* PSEUDO CODE FOR THIS:
             * if (leftCurrent is Unchanged)
             * {
             *     add(rightCurrent)
             * }
             * else if (rightCurrent is Unchanged)
             * {
             *     add(leftCurrent)
             * }
             * else if (leftCurrent is Replace || rightCurrent is Replace)
             * {
             *     if (leftCurrent == rightCurrent)
             *          add(leftCurrent)
             *     else
             *     {
             *          conflict = Conflict(leftCurrent, rightCurrent)
             *          add(conflict)
             *          conflicts.register(conflict)
             *     }
             * }
             * else if (leftCurrent is Changed && rightCurrent is Changed)
             * {
             *     add(algorithm.Merge(leftCurrent.ValueDiff, rightCurrent.ValueDiff, conflicts))
             * }
             * else
             *     throw
             */

            IMergeDiffsAlgorithm algorithm = this.aMergerImplementation.Partial.Algorithms.GetMergeDiffsAlgorithm(property.Type);
            Type itemReplacedType          = typeof(IDiffItemReplaced <>).MakeGenericType(property.Type);

            ParameterExpression conflict = Expression.Parameter(typeof(IDiffItemConflicted), "conflict");

            return(Expression.IfThenElse(
                       Expression.TypeIs(leftCurrent, typeof(IDiffItemUnchanged)),
                       Expression.Call(
                           ret,
                           ListMembers.Add(typeof(IDiffItem)),
                           rightCurrent
                           ),
                       Expression.IfThenElse(
                           Expression.TypeIs(rightCurrent, typeof(IDiffItemUnchanged)),
                           Expression.Call(
                               ret,
                               ListMembers.Add(typeof(IDiffItem)),
                               leftCurrent
                               ),
                           Expression.IfThenElse(
                               Expression.OrElse(
                                   Expression.TypeIs(leftCurrent, itemReplacedType),
                                   Expression.TypeIs(rightCurrent, itemReplacedType)
                                   ),
                               Expression.IfThenElse(
                                   Expression.Call(
                                       null,
                                       ObjectMembers.Equals(),
                                       leftCurrent,
                                       rightCurrent
                                       ),
                                   Expression.Call(
                                       ret,
                                       ListMembers.Add(typeof(IDiffItem)),
                                       leftCurrent
                                       ),
                                   Expression.Block(
                                       new[] { conflict },
                                       Expression.Assign(
                                           conflict,
                                           Expression.New(
                                               DiffItemsMembers.NewConflict(),
                                               leftCurrent,
                                               rightCurrent
                                               )
                                           ),
                                       Expression.Call(
                                           ret,
                                           ListMembers.Add(typeof(IDiffItem)),
                                           conflict
                                           ),
                                       Expression.Call(
                                           conflicts,
                                           ConflictContainerMembers.RegisterConflict(),
                                           conflict
                                           )
                                       )
                                   ),
                               Expression.IfThenElse(
                                   Expression.AndAlso(
                                       Expression.TypeIs(leftCurrent, typeof(IDiffItemChanged)),
                                       Expression.TypeIs(rightCurrent, typeof(IDiffItemChanged))
                                       ),
                                   Expression.Call(
                                       ret,
                                       ListMembers.Add(typeof(IDiffItem)),
                                       Expression.New(
                                           DiffItemsMembers.NewClassChanged(property.Type),
                                           Expression.Constant(property),
                                           Expression.Call(
                                               Expression.Constant(algorithm, typeof(IMergeDiffsAlgorithm <>).MakeGenericType(property.Type)),
                                               MergeDiffsAlgorithmMembers.MergeDiffs(property.Type),
                                               Expression.Property(
                                                   Expression.Convert(leftCurrent, typeof(IDiffItemChanged <>).MakeGenericType(property.Type)),
                                                   DiffItemsMembers.ChangedDiff(property.Type)
                                                   ),
                                               Expression.Property(
                                                   Expression.Convert(rightCurrent, typeof(IDiffItemChanged <>).MakeGenericType(property.Type)),
                                                   DiffItemsMembers.ChangedDiff(property.Type)
                                                   ),
                                               conflicts
                                               )
                                           )
                                       ),

                                   Expression.Throw(
                                       Expression.New(typeof(Exception))
                                       )
                                   )
                               )
                           )
                       ));
        }
Пример #6
0
        private Func <TType, TType, List <IDiffItem> > CompileDiff()
        {
            ParameterExpression ret = Expression.Parameter(typeof(List <IDiffItem>), "ret");

            ParameterExpression @base   = Expression.Parameter(typeof(TType), "base");
            ParameterExpression changed = Expression.Parameter(typeof(TType), "changed");

            Expression differ;

            if (this.aIDProperty == null)
            {
                differ = Expression.IfThen(
                    ExpressionExtensions.NotEqual(@base, changed),
                    Expression.Call(
                        ret,
                        ListMembers.Add(typeof(IDiffItem)),
                        Expression.New(
                            DiffItemsMembers.NewValueReplaced(typeof(TType)),
                            @base,
                            changed
                            )
                        )
                    );
            }
            else
            {
                differ = Expression.IfThen(
                    ExpressionExtensions.NotEqual(
                        Expression.Property(@base, this.aIDProperty.ReflectionPropertyInfo),
                        Expression.Property(changed, this.aIDProperty.ReflectionPropertyInfo)
                        ),
                    Expression.Call(
                        ret,
                        ListMembers.Add(typeof(IDiffItem)),
                        Expression.New(
                            DiffItemsMembers.NewValueReplaced(typeof(TType)),
                            @base,
                            changed
                            )
                        )
                    );
            }

            if (!typeof(TType).IsValueType)
            {
                differ = Expression.IfThenElse(
                    Expression.OrElse(
                        Expression.ReferenceEqual(@base, Expression.Constant(null)),
                        Expression.ReferenceEqual(changed, Expression.Constant(null))
                        ),
                    Expression.IfThen(
                        Expression.ReferenceEqual(@base, changed),
                        Expression.New(
                            DiffItemsMembers.NewValueReplaced(typeof(TType)),
                            @base,
                            changed
                            )
                        ),
                    differ
                    );
            }

            Expression <Func <TType, TType, List <IDiffItem> > > comparer = Expression.Lambda <Func <TType, TType, List <IDiffItem> > >(
                Expression.Block(
                    new[] { ret },
                    Expression.Assign(
                        ret,
                        Expression.New(
                            ListMembers.NewWithCount(typeof(IDiffItem)),
                            Expression.Constant(1)                             // maximum number of changes
                            )
                        ),
                    differ,
                    ret
                    ),
                @base,
                changed
                );

            return(comparer.Compile());
        }