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
- SubMenuStyle.cs
- ISAPIWorkerRequest.cs
- XmlLinkedNode.cs
- ObjectConverter.cs
- AspNetHostingPermission.cs
- NotFiniteNumberException.cs
- DiscreteKeyFrames.cs
- Sentence.cs
- FlowLayout.cs
- ManagedWndProcTracker.cs
- BinaryWriter.cs
- ConnectionModeReader.cs
- XsdCachingReader.cs
- MemoryMappedViewStream.cs
- XslVisitor.cs
- IfAction.cs
- WindowsListViewItemStartMenu.cs
- Adorner.cs
- RsaKeyGen.cs
- GeneralTransform.cs
- XmlSchemaInfo.cs
- SerializerWriterEventHandlers.cs
- ConnectionInterfaceCollection.cs
- GeneralTransform3DTo2DTo3D.cs
- XPathNavigator.cs
- UInt64.cs
- TableAutomationPeer.cs
- CrossAppDomainChannel.cs
- ServiceEndpoint.cs
- ResXResourceSet.cs
- DebugController.cs
- ExpressionPrefixAttribute.cs
- DbgUtil.cs
- VBIdentifierNameEditor.cs
- SchemaImporterExtension.cs
- WindowsTreeView.cs
- SqlParameterizer.cs
- TraceContextEventArgs.cs
- ReaderOutput.cs
- StringWriter.cs
- SchemeSettingElement.cs
- UserPersonalizationStateInfo.cs
- WebPartEventArgs.cs
- PromptStyle.cs
- MediaContextNotificationWindow.cs
- PathGeometry.cs
- SecurityResources.cs
- EdmType.cs
- SiteMapNode.cs
- DataGridViewTopLeftHeaderCell.cs
- Enumerable.cs
- TypeForwardedToAttribute.cs
- ChannelSinkStacks.cs
- TreeViewHitTestInfo.cs
- ReceiveDesigner.xaml.cs
- XpsResource.cs
- OdbcDataAdapter.cs
- TemplateEditingVerb.cs
- UpdatableGenericsFeature.cs
- XmlElementList.cs
- XpsS0ValidatingLoader.cs
- ValueSerializer.cs
- DocumentPageTextView.cs
- VersionValidator.cs
- WebBaseEventKeyComparer.cs
- ListMarkerSourceInfo.cs
- _AcceptOverlappedAsyncResult.cs
- DataBindingHandlerAttribute.cs
- CodeArrayIndexerExpression.cs
- SelectionRange.cs
- XpsThumbnail.cs
- Pointer.cs
- DispatchWrapper.cs
- NullableConverter.cs
- FlowDocumentPaginator.cs
- MissingMethodException.cs
- StateMachine.cs
- CodeTypeParameterCollection.cs
- Viewport2DVisual3D.cs
- CodeDefaultValueExpression.cs
- SecurityRuntime.cs
- AliasedSlot.cs
- CacheEntry.cs
- CompositeFontInfo.cs
- BitmapMetadataBlob.cs
- _SslSessionsCache.cs
- DataRelationPropertyDescriptor.cs
- SafeProcessHandle.cs
- GridViewRowCollection.cs
- HTMLTextWriter.cs
- WebBrowserProgressChangedEventHandler.cs
- RemoteHelper.cs
- MdbDataFileEditor.cs
- EventWaitHandle.cs
- wgx_render.cs
- SoapProcessingBehavior.cs
- RowBinding.cs
- BasicHttpSecurityMode.cs
- StringFunctions.cs
- TemplateParser.cs