Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / ArgumentFixer.cs / 1305376 / ArgumentFixer.cs
//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------- namespace System.Activities.Presentation { using System.Activities.Expressions; using System.ServiceModel.Activities; using System.Activities.Statements; using Microsoft.VisualBasic.Activities; using System.Collections.Generic; using System.Activities.Presentation.Model; using System.Activities.Presentation.Validation; using System.Linq; using System.Activities.ExpressionParser; using System.Activities.Validation; using System.Reflection; using System.ComponentModel; using System.Runtime; using System.Activities.Presentation.View; using System.Linq.Expressions; //base of helper class to fix one argument for one activity abstract class ActivityArgumentFixer { public abstract Type ActivityType { get; } public abstract bool NeedsToFix(Activity activity, ActivityWithResult expression, bool isLocation); public abstract void Fix(Activity activity, Argument newArgument); } class ActivityArgumentFixer: ActivityArgumentFixer where TActivity : Activity { Func argumentGetter; Action argumentSetter; public ActivityArgumentFixer(Func argumentGetter, Action argumentSetter) { this.argumentGetter = argumentGetter; this.argumentSetter = argumentSetter; } public override bool NeedsToFix(Activity activity, ActivityWithResult expression, bool isLocation) { TActivity concreteActivity = activity as TActivity; if (concreteActivity == null) { return false; } Argument argument = this.argumentGetter(concreteActivity, isLocation); return argument != null && argument.Expression == expression; } public override void Fix(Activity activity, Argument newArgument) { TActivity concreteActivity = activity as TActivity; if (concreteActivity == null) { return; } this.argumentSetter(concreteActivity, newArgument); } public override Type ActivityType { get { return typeof(TActivity); } } } //utility class to fix up invalid arguments for activities after validation static class ArgumentFixer { static Dictionary argumentFixers = new Dictionary (); public static void RegisterArgumentFixer (ActivityArgumentFixer fixer) { ArgumentFixer.argumentFixers[fixer.ActivityType] = fixer; } // // In some of our activities, such as non generic Assign, exposes arguments with no type constraints. // // In that case, the designer has to infer the type based on user entered expressions. // But those expression's inferred type changes when its context changes. // Such context includes (e.g. Namespaces, Variable definition, References ...) // // To maintain data laziness of our designers (so as to minimize user perceived latency), we postpone to // work of type re-inferencing until validation pass where we will need to walk the tree. // // This method is used to update the argument objects (and the underlying expression objects as well) // due to new type inferencing requirements. // // This is NOT the long term solution. Doing type inference right is not a realistic goal for Dev10 at // this stage now. This should be consider a patch so as to make a reasonable experience for Assign. // public static void UpdateInvalidArgumentsIfNecessary(object sender, ValidationService.ErrorsMarkedEventArgs args) { if (args.Reason != ValidationReason.ModelChange) { return; } // Re-compile erroreous expressions to see if update is necessary Dictionary lvalueReplacements = ComputeLocationExpressionReplacements( from error in args.Errors where IsVisualBasicReferenceForUntypedArgument(error.Source) select error, args.Context); Dictionary rvalueReplacements = ComputeValueExpressionReplacements( from error in args.Errors where IsVisualBasicValueForUntypedArgument(error.Source) select error, args.Context); using (EditingScope editingScope = args.ModelTreeManager.CreateEditingScope(string.Empty)) { editingScope.SuppressUndo = true; //Assign has special requirement that Value has to have the same type as To, so we need to track all Assign activities whose To have been changed Dictionary modifiedAssigns = new Dictionary (); foreach (ActivityWithResult expressionToFix in lvalueReplacements.Keys) { Type expectedType = lvalueReplacements[expressionToFix]; string expressionText = ExpressionHelper.GetExpressionString(expressionToFix); if (expressionToFix.ResultType.GetGenericArguments()[0] != expectedType) { args.Handled = true; Argument newArgument = ConstructNewArgument(true, expectedType, expressionText); ReplaceArgument(expressionToFix, newArgument, args.ModelTreeManager); } Assign modifiedAssign = ValidationService.GetParent(expressionToFix) as Assign; if (modifiedAssign != null) { modifiedAssigns.Add(modifiedAssign, expectedType); } } foreach (ActivityWithResult expressionToFix in rvalueReplacements.Keys) { Type expectedType = rvalueReplacements[expressionToFix]; string expressionText = ExpressionHelper.GetExpressionString(expressionToFix); // Here is where more type inferencing is happening. // Depending on context, r-value might not take the type inferred from the compiler. // // A classic example will be Assign string value to Nothing. By default, VB compiler // output object as the expected type which is not really what I want. // Assign assignToFix = ValidationService.GetParent(expressionToFix) as Assign; if (assignToFix != null) { if (modifiedAssigns.ContainsKey(assignToFix)) { expectedType = modifiedAssigns[assignToFix]; modifiedAssigns.Remove(assignToFix); } else if (assignToFix.To != null) { expectedType = assignToFix.To.ArgumentType; } } if (expressionToFix.ResultType != expectedType) { args.Handled = true; Argument newArgument = ConstructNewArgument(false, expectedType, expressionText); ReplaceArgument(expressionToFix, newArgument, args.ModelTreeManager); } } foreach (Assign otherAssign in modifiedAssigns.Keys) { if (otherAssign.Value != null) { ActivityWithResult offendingExpression = otherAssign.Value.Expression; Type expectedType = modifiedAssigns[otherAssign]; if (offendingExpression.ResultType != expectedType) { string expressionText = ExpressionHelper.GetExpressionString(offendingExpression); if (expressionText != null) { args.Handled = true; Argument newArgument = ConstructNewArgument(false, expectedType, expressionText); ReplaceArgument(offendingExpression, newArgument, args.ModelTreeManager); } // Since r-value of Assign could potentially be any other expression activities, but type inferencing will stop here. // There is no way to update expression activities now. } } } // The completion of this specific editing scope will NOT result in an UndoUnit. // This is done so to avoid infinite loop of validation -> fixup -> validation -> ... // This is also done to avoid undo -> fixup -> undo -> ... // See UndoEngine for details on how I skipped that. editingScope.Complete(); } } static Dictionary ComputeLocationExpressionReplacements(IEnumerable lvalueErrors, EditingContext context) { Dictionary lvalueReplacements = new Dictionary (); foreach (ValidationError lvalueError in lvalueErrors) { ActivityWithResult offendingExpression = (ActivityWithResult)lvalueError.Source; Type returnType; SourceExpressionException compileError; VisualBasicSettings settings; VisualBasicDesignerHelper.RecompileVisualBasicReference( offendingExpression, out returnType, out compileError, out settings); if (compileError == null) { lvalueReplacements.Add(offendingExpression, returnType); if (settings != null) { //merge with import designer foreach (VisualBasicImportReference reference in settings.ImportReferences) { ImportDesigner.AddImport(reference.Import, context); } } } } return lvalueReplacements; } static Dictionary ComputeValueExpressionReplacements(IEnumerable rvalueErrors, EditingContext context) { Dictionary rvalueReplacements = new Dictionary (); foreach (ValidationError rvalueError in rvalueErrors) { ActivityWithResult offendingExpression = (ActivityWithResult)rvalueError.Source; Type returnType; SourceExpressionException compileError; VisualBasicSettings settings; VisualBasicDesignerHelper.RecompileVisualBasicValue( offendingExpression, out returnType, out compileError, out settings); if (compileError == null) { rvalueReplacements.Add(offendingExpression, returnType); if (settings != null) { //merge with import designer foreach (VisualBasicImportReference reference in settings.ImportReferences) { ImportDesigner.AddImport(reference.Import, context); } } } } return rvalueReplacements; } static void ReplaceArgument(ActivityWithResult expressionToReplace, Argument newArgument, ModelTreeManager modelTreeManager) { ModelItem expressionModelItem = modelTreeManager.GetModelItem(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)) { ModelItem newArgumentModel = parentObject.Properties[argumentModelItem.Source.Name].SetValue(newArgument); //make sure argument.Expression is wrapped in ModelItem as well ModelItem newExpressionModel = newArgumentModel.Properties["Expression"].Value; } } } else { Activity parentActivity = ValidationService.GetParent(expressionToReplace); ActivityArgumentFixer fixer; if (ArgumentFixer.argumentFixers.TryGetValue(parentActivity.GetType(), out fixer)) { fixer.Fix(parentActivity, newArgument); } } } static Argument ConstructNewArgument(bool isLocationExpression, Type expectedType, string expressionText) { Argument newArgument = null; if (isLocationExpression) { newArgument = (Argument)Activator.CreateInstance(typeof(OutArgument<>).MakeGenericType(expectedType)); } else { newArgument = (Argument)Activator.CreateInstance(typeof(InArgument<>).MakeGenericType(expectedType)); } ActivityWithResult newExpression = ExpressionHelper.CreateExpression(expectedType, expressionText, isLocationExpression, null); newArgument.Expression = newExpression; return newArgument; } static bool IsGenericType(Type query, Type genericTypeDefintion) { return query.IsGenericType && query.GetGenericTypeDefinition() == genericTypeDefintion; } static bool IsVisualBasicReferenceForUntypedArgument(Activity expression) { if (!IsGenericType(expression.GetType(), typeof(VisualBasicReference<>))) { return false; } //only VB expressions for untyped arguments need to be fixed up, //however there is no way to tell which argument on expression belongs to so we only handle few activities //which are known to have untyped arguments now. Activity parentActivity = ValidationService.GetParent(expression); ActivityArgumentFixer fixer; if (!ArgumentFixer.argumentFixers.TryGetValue(parentActivity.GetType(), out fixer)) { return false; } return fixer.NeedsToFix(parentActivity, expression as ActivityWithResult, true); } static bool IsVisualBasicValueForUntypedArgument(Activity expression) { if (!IsGenericType(expression.GetType(), typeof(VisualBasicValue<>))) { return false; } //only VB expressions for untyped arguments need to be fixed up, //however there is no way to tell which argument on expression belongs to so we only handle few activities //which are known to have untyped arguments now. Activity parentActivity = ValidationService.GetParent(expression); ActivityArgumentFixer fixer; if (!ArgumentFixer.argumentFixers.TryGetValue(parentActivity.GetType(), out fixer)) { return false; } return fixer.NeedsToFix(parentActivity, expression as ActivityWithResult, false); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RemotingConfigParser.cs
- CanonicalFontFamilyReference.cs
- _TLSstream.cs
- ItemsControl.cs
- MetadataElement.cs
- OutputCacheSettings.cs
- UIInitializationException.cs
- LogPolicy.cs
- EditorPartCollection.cs
- Point3DAnimation.cs
- FormViewInsertEventArgs.cs
- UICuesEvent.cs
- TemplateKeyConverter.cs
- Emitter.cs
- ShaderEffect.cs
- SystemPens.cs
- Errors.cs
- PropertyEmitter.cs
- PropertyKey.cs
- GetChildSubtree.cs
- MethodBuilderInstantiation.cs
- PersonalizationStateInfo.cs
- ReadOnlyDictionary.cs
- SystemNetworkInterface.cs
- ADRoleFactoryConfiguration.cs
- Assert.cs
- SelectionItemPattern.cs
- CommandBindingCollection.cs
- BitConverter.cs
- WebPartZoneCollection.cs
- ThreadExceptionEvent.cs
- CompositeCollection.cs
- QueryResults.cs
- HyperLinkDataBindingHandler.cs
- GPRECT.cs
- WebPartDisplayModeCancelEventArgs.cs
- PropertyGridEditorPart.cs
- ApplicationSettingsBase.cs
- FacetChecker.cs
- Semaphore.cs
- GuidelineSet.cs
- RelatedCurrencyManager.cs
- QueryPageSettingsEventArgs.cs
- PartialToken.cs
- DataKeyArray.cs
- ClientRuntimeConfig.cs
- Preprocessor.cs
- MediaTimeline.cs
- AdornerPresentationContext.cs
- ToolStripMenuItem.cs
- ToolStripKeyboardHandlingService.cs
- HtmlLinkAdapter.cs
- SafeMILHandle.cs
- DataServiceHost.cs
- KeyGesture.cs
- SHA1.cs
- InternalControlCollection.cs
- NetworkAddressChange.cs
- GrammarBuilderBase.cs
- LingerOption.cs
- SplitterCancelEvent.cs
- ConsoleCancelEventArgs.cs
- PenThreadPool.cs
- EventHandlers.cs
- WebBrowsableAttribute.cs
- SafeEventLogWriteHandle.cs
- PackagePart.cs
- ElementInit.cs
- DataRow.cs
- RegexGroupCollection.cs
- AddingNewEventArgs.cs
- TemplateBindingExpressionConverter.cs
- ColorComboBox.cs
- CommandHelpers.cs
- FixedSOMTable.cs
- Operators.cs
- LoginName.cs
- BinaryVersion.cs
- _HeaderInfo.cs
- InstanceHandleReference.cs
- Tuple.cs
- ListenerHandler.cs
- WriteableOnDemandStream.cs
- BasicDesignerLoader.cs
- SByteConverter.cs
- DataGridParentRows.cs
- BuildProvider.cs
- XmlSerializationWriter.cs
- HttpSocketManager.cs
- BoolExpressionVisitors.cs
- QueryResponse.cs
- CodeComment.cs
- ExceptionTrace.cs
- FontFamily.cs
- SettingsProperty.cs
- Vector3DCollection.cs
- designeractionlistschangedeventargs.cs
- PersistenceException.cs
- BrowserCapabilitiesCodeGenerator.cs
- InputProcessorProfilesLoader.cs