internal static void UpdateInvalidArgumentsIfNecessary(object sender, ValidationService.ErrorsMarkedEventArgs args)
        {
            if (args.Reason != ValidationReason.ModelChange)
            {
                return;
            }

            if (args.Errors.Count == 0)
            {
                return;
            }

            using (EditingScope editingScope = args.ModelTreeManager.CreateEditingScope(string.Empty))
            {
                // Prevent the validation -> fix arguments -> validation loop.
                editingScope.SuppressUndo = true;

                // Suppress validation. We will do it ourselves (see below)
                editingScope.SuppressValidationOnComplete = true;

                // Re-compile erroreous expressions to see if update is necessary
                ValidationService validationService = args.Context.Services.GetRequiredService<ValidationService>();
                ArgumentAccessorWrapperCache argumentAccessorWrapperCache = new ArgumentAccessorWrapperCache();
                List<ExpressionReplacement> expressionReplacements = ComputeExpressionReplacements(args.Errors.Select(error => error.Source).OfType<ActivityWithResult>(), args.Context, argumentAccessorWrapperCache);
                bool argumentReplacementOccurred = false;
                if (expressionReplacements.Count > 0)
                {
                    try
                    {
                        foreach (ExpressionReplacement expressionReplacement in expressionReplacements)
                        {
                            if (expressionReplacement.TryReplaceArgument(args.ModelTreeManager, validationService))
                            {
                                argumentReplacementOccurred = true;
                            }
                        }

                        if (argumentReplacementOccurred)
                        {
                            args.Handled = true;
                            editingScope.Complete();
                        }
                    }
                    catch (Exception e)
                    {
                        if (Fx.IsFatal(e))
                        {
                            throw;
                        }

                        // We handle exception here instead of letting WF Designer handle it, so that the validation below will run even
                        // if any of the ArgumentAccessor.Setter methods throw exceptions.
                        ErrorReporting.ShowErrorMessage(e);
                    }

                    // Since any pending validation will be canceled if argument replacement occured (=has model change), we need to re-validate the workflow.
                    // We suppressed validation upon EditingScope completion and do it ourselves, because
                    // the argument replacement could have been done directly to the underlying activity instance, rather than thru ModelItem.
                    if (argumentReplacementOccurred)
                    {
                        validationService.ValidateWorkflow();
                    }
                }
            }
        }
            public bool TryReplaceArgument(ModelTreeManager modelTreeManager, ValidationService validationService)
            {
                Fx.Assert(modelTreeManager != null, "modelTreeManager cannot be null.");
                Fx.Assert(validationService != null, "validationService cannot be null.");

                ModelItem expressionModelItem = modelTreeManager.GetModelItem(this.ExpressionToReplace);
                if (expressionModelItem != null)
                {
                    ModelItem argumentModelItem = expressionModelItem.Parent;
                    ModelItem parentObject = argumentModelItem.Parent;

                    if (argumentModelItem.Source != null)
                    {
                        ModelProperty argumentProperty = parentObject.Properties[argumentModelItem.Source.Name];
                        Type argumentPropertyType = argumentProperty.PropertyType;
                        if (argumentPropertyType == typeof(InArgument) || argumentPropertyType == typeof(OutArgument) || argumentPropertyType == typeof(InOutArgument))
                        {
                            ModelItem oldArgumentModel = argumentProperty.Value;
                            ModelItem newArgumentModel = argumentProperty.SetValue(this.NewArgument);

                            // Make sure argument.Expression is wrapped in ModelItem as well
                            ModelItem newExpressionModel = newArgumentModel.Properties["Expression"].Value;

                            return true;
                        }
                    }
                }
                else
                {
                    Activity parentActivity = ValidationService.GetParent(this.ExpressionToReplace);
                    if (this.ArgumentAccessor.Setter != null)
                    {
                        try
                        {
                            validationService.DeactivateValidation();
                            this.ArgumentAccessor.Setter(parentActivity, this.NewArgument);
                            return true;
                        }
                        finally
                        {
                            validationService.ActivateValidation();
                        }
                    }
                }

                return false;
            }