Esempio n. 1
0
 /// <summary>
 /// Gets the type of the dependency root object for the specified property.
 /// </summary>
 /// <param name="difference">The difference.</param>
 /// <param name="accessor">The property accessor.</param>
 /// <returns>The type of the dependency root object for the specified property;
 /// <see langword="null" />, if none.</returns>
 /// <remarks>
 /// Returns <paramref name="accessor"/>.<see cref="PropertyAccessor.DependencyRootType"/>
 /// by default.
 /// </remarks>
 protected virtual Type GetDependencyRootType(Difference difference, PropertyAccessor accessor)
 {
     return(accessor.DependencyRootType);
 }
Esempio n. 2
0
 /// <summary>
 /// Determines whether specified property is mutable.
 /// </summary>
 /// <param name="difference">The difference.</param>
 /// <param name="accessor">The property accessor.</param>
 /// <returns><see langword="true"/> if th specified property is mutable;
 /// otherwise, <see langword="false"/>.
 /// </returns>
 /// <remarks>
 /// Returns <paramref name="accessor"/>.<see cref="PropertyAccessor.IsVolatile"/>
 /// by default.
 /// </remarks>
 protected virtual bool IsVolatile(Difference difference, PropertyAccessor accessor)
 {
     return(accessor.IsVolatile);
 }
Esempio n. 3
0
 /// <summary>
 /// Visits the unknown difference.
 /// </summary>
 /// <param name="difference">The difference.</param>
 /// <returns>
 /// A sequence of actions that must be performed to upgrade
 /// from <see cref="IDifference.Source"/> of the specified
 /// difference to its <see cref="IDifference.Target"/>.
 /// </returns>
 /// <exception cref="NotSupportedException">Always thrown by this method.</exception>
 protected virtual void VisitUnknownDifference(Difference difference)
 {
     throw new NotSupportedException();
 }
Esempio n. 4
0
        /// <inheritdoc/>
        /// <exception cref="ArgumentOutOfRangeException"><c>hints.SourceModel</c> or <c>hints.TargetModel</c>
        /// is out of range.</exception>
        /// <exception cref="InvalidOperationException">Upgrade sequence validation has failed.</exception>
        public ReadOnlyList <NodeAction> GetUpgradeSequence(Difference difference, HintSet hints, IComparer comparer)
        {
            ArgumentValidator.EnsureArgumentNotNull(hints, "hints");
            ArgumentValidator.EnsureArgumentNotNull(comparer, "comparer");
            if (difference == null)
            {
                return(new ReadOnlyList <NodeAction>(Enumerable.Empty <NodeAction>().ToList()));
            }

            TemporaryRenames = new Dictionary <string, Node>(StringComparer.OrdinalIgnoreCase);
            SourceModel      = (IModel)difference.Source;
            TargetModel      = (IModel)difference.Target;
            Hints            = hints ?? new HintSet(SourceModel, TargetModel);
            Comparer         = comparer;
            if (Hints.SourceModel != SourceModel)
            {
                throw new ArgumentOutOfRangeException("hints.SourceModel");
            }
            if (Hints.TargetModel != TargetModel)
            {
                throw new ArgumentOutOfRangeException("hints.TargetModel");
            }

            CurrentModel = (IModel)SourceModel.Clone(null, SourceModel.Name);
            Difference   = difference;
            var previous = currentAsync.Value;

            currentAsync.Value = this;
            using (NullActionHandler.Instance.Activate()) {
                try {
                    var actions = new GroupingNodeAction();

                    ProcessStage(UpgradeStage.CleanupData, actions);
                    ProcessStage(UpgradeStage.Prepare, actions);
                    ProcessStage(UpgradeStage.TemporaryRename, actions);
                    ProcessStage(UpgradeStage.Upgrade, actions);
                    ProcessStage(UpgradeStage.CopyData, actions);
                    ProcessStage(UpgradeStage.PostCopyData, actions);
                    ProcessStage(UpgradeStage.Cleanup, actions);

                    var validationHints = new HintSet(CurrentModel, TargetModel);
                    Hints.OfType <IgnoreHint>().ForEach(validationHints.Add);
                    var diff = comparer.Compare(CurrentModel, TargetModel, validationHints);
                    if (diff != null)
                    {
                        CoreLog.InfoRegion(Strings.LogAutomaticUpgradeSequenceValidation);
                        CoreLog.Info(Strings.LogValidationFailed);
                        CoreLog.Info(Strings.LogItemFormat, Strings.Difference);
                        CoreLog.Info("{0}", diff);
                        CoreLog.Info(Strings.LogItemFormat + "\r\n{1}", Strings.UpgradeSequence,
                                     new ActionSequence()
                        {
                            actions
                        });
                        CoreLog.Info(Strings.LogItemFormat, Strings.ExpectedTargetModel);
                        TargetModel.Dump();
                        CoreLog.Info(Strings.LogItemFormat, Strings.ActualTargetModel);
                        CurrentModel.Dump();
                        throw new InvalidOperationException(Strings.ExUpgradeSequenceValidationFailure);
                    }
                    return(new ReadOnlyList <NodeAction>(actions.Actions, true));
                }
                finally {
                    currentAsync.Value = previous;
                }
            }
        }
Esempio n. 5
0
 /// <inheritdoc/>
 /// <exception cref="ArgumentOutOfRangeException"><c>hints.SourceModel</c> or <c>hints.TargetModel</c>
 /// is out of range.</exception>
 public ReadOnlyList <NodeAction> GetUpgradeSequence(Difference difference, HintSet hints)
 {
     return(GetUpgradeSequence(difference, hints, new Comparer()));
 }
Esempio n. 6
0
        /// <summary>
        /// Compares source and target node properties.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="target">The target.</param>
        /// <param name="difference">The difference.</param>
        protected virtual void CompareProperties(Node source, Node target, NodeDifference difference)
        {
            var any = source ?? target;

            foreach (var pair in any.PropertyAccessors)
            {
                var accessor = pair.Value;
                if (accessor.IgnoreInComparison)
                {
                    continue;
                }

                var property = accessor.PropertyInfo;
                using (CreateContext().Activate()) {
                    Context.PropertyAccessor = accessor;
                    object sourceValue = (source == null || !accessor.HasGetter)
            ? accessor.Default : accessor.Getter.Invoke(source);
                    object targetValue = (target == null || !accessor.HasGetter)
            ? accessor.Default : accessor.Getter.Invoke(target);
                    object anyValue = sourceValue ?? targetValue;
                    if (anyValue == null)
                    {
                        continue; // Both are null
                    }
                    Difference propertyDifference = null;
                    if (!IsReference(sourceValue, targetValue))
                    {
                        propertyDifference = Visit(sourceValue, targetValue);
                    }
                    else if (Stage == ComparisonStage.ReferenceComparison)
                    {
                        if (IsIgnored(sourceValue))
                        {
                            difference.MovementInfo = 0;
                        }
                        else
                        {
                            propertyDifference = GetReferencedPropertyDifference(sourceValue, targetValue, target, property.Name);
                        }
                    }

                    if (propertyDifference == null)
                    {
                        continue;
                    }

                    if (any.Nesting.PropertyInfo != null && accessor.DependencyRootType == any.Nesting.PropertyInfo.PropertyType)
                    {
                        if (propertyDifference is NodeDifference)
                        {
                            ((NodeDifference)propertyDifference).IsDependentOnParent = true;
                        }
                        else if (propertyDifference is NodeCollectionDifference)
                        {
                            ((NodeCollectionDifference)propertyDifference).ItemChanges
                            .ForEach(item => item.IsDependentOnParent = true);
                        }
                    }
                    difference.PropertyChanges.Add(property.Name, propertyDifference);
                }
            }
        }