1 //----------------------------------------------------------------
2 // <copyright company="Microsoft Corporation">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //----------------------------------------------------------------
7 namespace System.Activities.Core.Presentation
9 using System.Activities.Expressions;
10 using System.Activities.Presentation;
11 using System.Activities.Presentation.Metadata;
12 using System.Activities.Presentation.Model;
13 using System.Activities.Statements;
14 using System.Activities.Validation;
15 using System.Collections.Generic;
16 using System.Collections.ObjectModel;
17 using System.Globalization;
18 using System.Reflection;
22 internal class InvokeDelegateValidationFeature : DesignTimeValidationFeature
24 private List<Constraint> constraints;
25 private EditingContext editingContext;
27 protected override Type ApplyTo
29 get { return typeof(InvokeDelegate); }
32 protected override IList<Constraint> DesignTimeConstraints
36 if (this.constraints == null)
38 this.constraints = new List<Constraint> { this.CreateCheckDelegateRule(this.editingContext) };
41 return this.constraints;
45 public override void Initialize(EditingContext context, Type modelType)
47 this.editingContext = context;
48 base.Initialize(context, modelType);
51 private Constraint CreateCheckDelegateRule(EditingContext editingContext)
53 DelegateInArgument<InvokeDelegate> invokeDelegate = new DelegateInArgument<InvokeDelegate>();
54 DelegateInArgument<ValidationContext> context = new DelegateInArgument<ValidationContext>();
56 return new Constraint<InvokeDelegate>
58 Body = new ActivityAction<InvokeDelegate, ValidationContext>
60 Argument1 = invokeDelegate,
62 Handler = new CheckDelegateRule
64 Activity = invokeDelegate,
65 EditingContext = editingContext,
71 private class CheckDelegateRule : NativeActivity
73 public CheckDelegateRule()
75 this.WarningMessageVariable = new Variable<string>();
76 this.ErrorMessageVariable = new Variable<string>();
77 this.ShowWarning = new AssertValidation()
81 Message = new VariableValue<string> { Variable = this.WarningMessageVariable }
83 this.ShowError = new AssertValidation()
87 Message = new VariableValue<string> { Variable = this.ErrorMessageVariable }
92 public InArgument<InvokeDelegate> Activity { get; set; }
94 public EditingContext EditingContext { get; set; }
96 private Variable<string> WarningMessageVariable { get; set; }
98 private Variable<string> ErrorMessageVariable { get; set; }
100 private AssertValidation ShowWarning { get; set; }
102 private AssertValidation ShowError { get; set; }
104 protected override void CacheMetadata(NativeActivityMetadata metadata)
106 RuntimeArgument activityArgument = new RuntimeArgument("Activity", typeof(InvokeDelegate), ArgumentDirection.In, true);
107 metadata.Bind(this.Activity, activityArgument);
108 metadata.SetArgumentsCollection(new Collection<RuntimeArgument> { activityArgument });
110 metadata.AddImplementationChild(this.ShowWarning);
111 metadata.AddImplementationChild(this.ShowError);
112 metadata.AddImplementationVariable(this.WarningMessageVariable);
113 metadata.AddImplementationVariable(this.ErrorMessageVariable);
116 protected override void Execute(NativeActivityContext context)
118 StringBuilder errorBuilder = new StringBuilder();
119 InvokeDelegate activity = this.Activity.Get(context);
121 string reference = PropertyReferenceUtilities.GetPropertyReference(activity, "Delegate");
123 if (reference != null)
125 DynamicActivityProperty property = null;
127 ModelTreeManager manager = this.EditingContext.Services.GetService<ModelTreeManager>();
128 if (manager.Root.ItemType == typeof(ActivityBuilder))
130 property = DynamicActivityPropertyUtilities.Find(manager.Root.Properties["Properties"].Collection, reference);
133 if (property == null)
135 this.EmitValidationError(context, string.Format(CultureInfo.CurrentUICulture, SR.PropertyReferenceNotResolved, reference));
139 if (property.Type == typeof(ActivityDelegate))
141 this.EmitValidationWarning(context, string.Format(CultureInfo.CurrentUICulture, SR.PropertyIsNotAConcreteActivityDelegate, reference));
145 if (!property.Type.IsSubclassOf(typeof(ActivityDelegate)))
147 this.EmitValidationError(context, string.Format(CultureInfo.CurrentUICulture, SR.PropertyIsNotAnActivityDelegate, reference));
151 if (property.Type.IsAbstract)
153 this.EmitValidationWarning(context, string.Format(CultureInfo.CurrentUICulture, SR.PropertyIsNotAConcreteActivityDelegate, reference));
157 ActivityDelegateMetadata metadata = ActivityDelegateUtilities.GetMetadata(property.Type);
159 if (activity.DelegateArguments.Count != metadata.Count)
161 this.EmitValidationWarning(context, SR.WrongNumberOfArgumentsForActivityDelegate);
165 foreach (ActivityDelegateArgumentMetadata expectedArgument in metadata)
167 Argument delegateArgument = null;
169 if (activity.DelegateArguments.TryGetValue(expectedArgument.Name, out delegateArgument))
171 if ((expectedArgument.Direction == ActivityDelegateArgumentDirection.In && delegateArgument.Direction != ArgumentDirection.In) ||
172 (expectedArgument.Direction == ActivityDelegateArgumentDirection.Out && delegateArgument.Direction != ArgumentDirection.Out))
174 errorBuilder.AppendFormat(CultureInfo.CurrentUICulture, SR.DelegateArgumentsDirectionalityMismatch, expectedArgument.Name, delegateArgument.Direction, expectedArgument.Direction);
177 if (delegateArgument.ArgumentType != expectedArgument.Type)
179 if (expectedArgument.Direction == ActivityDelegateArgumentDirection.In)
181 if (!TypeHelper.AreTypesCompatible(delegateArgument.ArgumentType, expectedArgument.Type))
183 errorBuilder.AppendFormat(CultureInfo.CurrentUICulture, SR.DelegateInArgumentTypeMismatch, expectedArgument.Name, expectedArgument.Type, delegateArgument.ArgumentType);
188 if (!TypeHelper.AreTypesCompatible(expectedArgument.Type, delegateArgument.ArgumentType))
190 errorBuilder.AppendFormat(CultureInfo.CurrentUICulture, SR.DelegateOutArgumentTypeMismatch, expectedArgument.Name, expectedArgument.Type, delegateArgument.ArgumentType);
197 errorBuilder.AppendFormat(CultureInfo.CurrentUICulture, SR.DelegateArgumentMissing, expectedArgument.Name);
201 if (errorBuilder.Length > 0)
203 this.EmitValidationWarning(context, errorBuilder.ToString());
208 private void EmitValidationWarning(NativeActivityContext context, string message)
210 this.WarningMessageVariable.Set(context, message);
211 context.ScheduleActivity(this.ShowWarning);
214 private void EmitValidationError(NativeActivityContext context, string message)
216 this.ErrorMessageVariable.Set(context, message);
217 context.ScheduleActivity(this.ShowError);