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
- WebControlParameterProxy.cs
- brushes.cs
- FormatterServices.cs
- Constants.cs
- XmlNavigatorStack.cs
- ComponentEvent.cs
- NavigationWindow.cs
- HttpResponseInternalWrapper.cs
- ScriptReferenceBase.cs
- FreeFormPanel.cs
- Condition.cs
- FixedSOMElement.cs
- DocumentReferenceCollection.cs
- Timer.cs
- BitmapImage.cs
- XmlElementCollection.cs
- SuppressIldasmAttribute.cs
- RIPEMD160.cs
- Collection.cs
- ScrollProperties.cs
- ClassDataContract.cs
- listitem.cs
- TextOnlyOutput.cs
- Converter.cs
- UnauthorizedWebPart.cs
- KeyFrames.cs
- SystemIPv6InterfaceProperties.cs
- RotationValidation.cs
- ContentElementAutomationPeer.cs
- DataTable.cs
- PreProcessor.cs
- ConfigDefinitionUpdates.cs
- DbXmlEnabledProviderManifest.cs
- DesignTimeTemplateParser.cs
- CommandID.cs
- Dictionary.cs
- EntityCollection.cs
- ChannelRequirements.cs
- RemotingException.cs
- OleDbErrorCollection.cs
- AddingNewEventArgs.cs
- AuthenticationModulesSection.cs
- WindowsAuthenticationEventArgs.cs
- Animatable.cs
- WebPartTransformerCollection.cs
- OracleLob.cs
- X509Utils.cs
- MarkerProperties.cs
- SQLMembershipProvider.cs
- XPathDocumentBuilder.cs
- TypeNameConverter.cs
- XamlStackWriter.cs
- SiteMapNode.cs
- TypeSource.cs
- OleDbDataAdapter.cs
- LinqDataSourceView.cs
- AccessDataSource.cs
- InkPresenter.cs
- PhoneCall.cs
- Content.cs
- GeneralTransform3DTo2D.cs
- WebPartEditorApplyVerb.cs
- cookiecontainer.cs
- ValidationUtility.cs
- ConfigurationSectionCollection.cs
- MulticastIPAddressInformationCollection.cs
- ParallelTimeline.cs
- AutomationEvent.cs
- FontWeight.cs
- ConfigurationSettings.cs
- LinkLabelLinkClickedEvent.cs
- ProvideValueServiceProvider.cs
- Deserializer.cs
- HuffModule.cs
- SqlConnection.cs
- SRDisplayNameAttribute.cs
- Size3DValueSerializer.cs
- BindingMAnagerBase.cs
- PageOrientation.cs
- DateTimeEditor.cs
- SqlAliaser.cs
- GiveFeedbackEventArgs.cs
- XmlTextReaderImpl.cs
- MappingException.cs
- InstalledFontCollection.cs
- ViewDesigner.cs
- CallbackCorrelationInitializer.cs
- BufferedWebEventProvider.cs
- DesignerActionVerbItem.cs
- NameValueSectionHandler.cs
- Cursor.cs
- DynamicDataRoute.cs
- LocalizabilityAttribute.cs
- CompiledRegexRunner.cs
- ObjectDataSourceEventArgs.cs
- EditorBrowsableAttribute.cs
- CanonicalFontFamilyReference.cs
- CodeRegionDirective.cs
- RegexGroupCollection.cs
- TimelineCollection.cs