1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //-----------------------------------------------------------------------------
4 
5 namespace System.Activities
6 {
7     using System;
8     using System.Activities.DynamicUpdate;
9     using System.Activities.Expressions;
10     using System.Activities.Hosting;
11     using System.Activities.Runtime;
12     using System.Activities.Validation;
13     using System.Activities.XamlIntegration;
14     using System.Collections;
15     using System.Collections.Generic;
16     using System.Collections.ObjectModel;
17     using System.ComponentModel;
18     using System.Diagnostics.CodeAnalysis;
19     using System.Globalization;
20     using System.Linq;
21     using System.Runtime;
22     using System.Threading;
23     using System.Windows.Markup;
24     using System.Xaml;
25 
26     [ContentProperty("Implementation")]
27     public abstract class Activity
28     {
29         const string generatedArgumentPrefix = "Argument";
30         static int nextCacheId;
31 
32         static readonly IList<Activity> emptyChildren = new List<Activity>(0);
33         static readonly IList<Variable> emptyVariables = new List<Variable>(0);
34         static readonly IList<RuntimeArgument> emptyArguments = new List<RuntimeArgument>(0);
35         static readonly IList<ActivityDelegate> emptyDelegates = new List<ActivityDelegate>(0);
36 
37         internal static readonly ReadOnlyCollection<Constraint> EmptyConstraints = new ReadOnlyCollection<Constraint>(new Constraint[0]);
38 
39         string displayName;
40         bool isDisplayNameSet;
41         int id;
42         RootProperties rootProperties;
43 
44         IList<RuntimeArgument> arguments;
45 
46         IList<Activity> children;
47         IList<Activity> implementationChildren;
48         IList<Activity> importedChildren;
49 
50         IList<ActivityDelegate> delegates;
51         IList<ActivityDelegate> implementationDelegates;
52         IList<ActivityDelegate> importedDelegates;
53 
54         IList<Variable> variables;
55         IList<Variable> implementationVariables;
56 
57         IList<ValidationError> tempValidationErrors;
58         IList<RuntimeArgument> tempAutoGeneratedArguments;
59 
60         Collection<Constraint> constraints;
61         Activity runtimeImplementation;
62 
63         Activity rootActivity;
64         object thisLock;
65 
66         QualifiedId qualifiedId;
67 
68         // For a given cacheId this tells us whether we've called InternalCacheMetadata yet or not
69         CacheStates isMetadataCached;
70         int cacheId;
71 
72         RelationshipType relationshipToParent;
73         Nullable<bool> isSubtreeEmpty;
74 
75         int symbolCount;
76 
77         // alternatives are extended through DynamicActivity, CodeActivity, and NativeActivity
Activity()78         protected Activity()
79         {
80             this.thisLock = new object();
81         }
82 
83         [TypeConverter(typeof(ImplementationVersionConverter))]
84         [DefaultValue(null)]
85         protected virtual internal Version ImplementationVersion
86         {
87             get;
88             set;
89         }
90 
91         [XamlDeferLoad(typeof(FuncDeferringLoader), typeof(Activity))]
92         [DefaultValue(null)]
93         [Browsable(false)]
94         [Ambient]
95         protected virtual Func<Activity> Implementation
96         {
97             get;
98             set;
99         }
100 
101         protected Collection<Constraint> Constraints
102         {
103             get
104             {
105                 if (this.constraints == null)
106                 {
107                     this.constraints = new Collection<Constraint>();
108                 }
109                 return this.constraints;
110             }
111         }
112 
113         protected internal int CacheId
114         {
115             get
116             {
117                 return this.cacheId;
118             }
119         }
120 
121         internal RelationshipType RelationshipToParent
122         {
123             get
124             {
125                 return this.relationshipToParent;
126             }
127         }
128 
129         internal bool HasNonEmptySubtree
130         {
131             get
132             {
133                 if (this.isSubtreeEmpty.HasValue)
134                 {
135                     return !this.isSubtreeEmpty.Value;
136                 }
137                 else
138                 {
139                     if (this.Children.Count > 0 || this.ImplementationChildren.Count > 0 || this.ImportedChildren.Count > 0 ||
140                         this.Delegates.Count > 0 || this.ImplementationDelegates.Count > 0 || this.ImportedDelegates.Count > 0 ||
141                         this.RuntimeVariables.Count > 0 || this.ImplementationVariables.Count > 0 ||
142                         this.RuntimeArguments.Count > 0)
143                     {
144                         this.isSubtreeEmpty = false;
145                     }
146                     else
147                     {
148                         this.isSubtreeEmpty = true;
149                     }
150                     return !this.isSubtreeEmpty.Value;
151                 }
152             }
153         }
154 
155         internal int SymbolCount
156         {
157             get
158             {
159                 return this.symbolCount;
160             }
161         }
162 
163         internal IdSpace MemberOf
164         {
165             get;
166             set;
167         }
168 
169         internal IdSpace ParentOf
170         {
171             get;
172             set;
173         }
174 
175         internal QualifiedId QualifiedId
176         {
177             get
178             {
179                 if (this.qualifiedId == null)
180                 {
181                     this.qualifiedId = new QualifiedId(this);
182                 }
183 
184                 return this.qualifiedId;
185             }
186         }
187 
188         // This flag governs special behavior that we need to keep for back-compat on activities
189         // that implemented TryGetValue in 4.0.
190         internal bool UseOldFastPath
191         {
192             get;
193             set;
194         }
195 
196         internal bool SkipArgumentResolution
197         {
198             get;
199             set;
200         }
201 
202         internal bool IsFastPath
203         {
204             get
205             {
206                 return this.SkipArgumentResolution && IsActivityWithResult;
207             }
208         }
209 
210         internal virtual bool IsActivityWithResult
211         {
212             get
213             {
214                 return false;
215             }
216         }
217 
218         internal object Origin
219         {
220             get;
221             set;
222         }
223 
224         public string DisplayName
225         {
226             get
227             {
228                 if (!this.isDisplayNameSet && string.IsNullOrEmpty(this.displayName))
229                 {
230                     this.displayName = ActivityUtilities.GetDisplayName(this);
231                 }
232 
233                 return this.displayName;
234             }
235             set
236             {
237                 if (value == null)
238                 {
239                     this.displayName = string.Empty;
240                 }
241                 else
242                 {
243                     this.displayName = value;
244                 }
245                 this.isDisplayNameSet = true;
246             }
247         }
248 
249         public string Id
250         {
251             get
252             {
253                 if (this.id == 0)
254                 {
255                     return null;
256                 }
257                 else
258                 {
259                     return this.QualifiedId.ToString();
260                 }
261             }
262         }
263 
264         internal bool IsExpressionRoot
265         {
266             get
267             {
268                 return this.relationshipToParent == RelationshipType.ArgumentExpression;
269             }
270         }
271 
272         internal bool HasStartedCachingMetadata
273         {
274             get
275             {
276                 return this.isMetadataCached != CacheStates.Uncached;
277             }
278         }
279 
280         internal bool IsMetadataCached
281         {
282             get
283             {
284                 return this.isMetadataCached != CacheStates.Uncached;
285             }
286         }
287 
288         internal bool IsMetadataFullyCached
289         {
290             get
291             {
292                 return (this.isMetadataCached & CacheStates.Full) == CacheStates.Full;
293             }
294         }
295 
296         internal bool IsRuntimeReady
297         {
298             get
299             {
300                 return (this.isMetadataCached & CacheStates.RuntimeReady) == CacheStates.RuntimeReady;
301             }
302         }
303 
304         internal Activity RootActivity
305         {
306             get
307             {
308                 return this.rootActivity;
309             }
310         }
311 
312         internal int InternalId
313         {
314             get
315             {
316                 return this.id;
317             }
318             set
319             {
320                 Fx.Assert(value != 0, "0 is an invalid ID");
321                 ClearIdInfo();
322                 this.id = value;
323             }
324         }
325 
326         internal ActivityDelegate HandlerOf
327         {
328             get;
329             private set;
330         }
331 
332         internal Activity Parent
333         {
334             get;
335             private set;
336         }
337 
338         internal LocationReferenceEnvironment HostEnvironment
339         {
340             get
341             {
342                 if (this.RootActivity != null && this.RootActivity.rootProperties != null)
343                 {
344                     return this.RootActivity.rootProperties.HostEnvironment;
345                 }
346 
347                 return null;
348             }
349         }
350 
351         internal IList<RuntimeArgument> RuntimeArguments
352         {
353             get
354             {
355                 return this.arguments;
356             }
357         }
358 
359         internal IList<Activity> Children
360         {
361             get
362             {
363                 return this.children;
364             }
365         }
366 
367         internal IList<Activity> ImplementationChildren
368         {
369             get
370             {
371                 return this.implementationChildren;
372             }
373         }
374 
375         internal IList<Activity> ImportedChildren
376         {
377             get
378             {
379                 return this.importedChildren;
380             }
381         }
382 
383         internal IList<ActivityDelegate> Delegates
384         {
385             get
386             {
387                 return this.delegates;
388             }
389         }
390 
391         internal IList<ActivityDelegate> ImplementationDelegates
392         {
393             get
394             {
395                 return this.implementationDelegates;
396             }
397         }
398 
399         internal IList<ActivityDelegate> ImportedDelegates
400         {
401             get
402             {
403                 return this.importedDelegates;
404             }
405         }
406 
407         internal bool HasBeenAssociatedWithAnInstance
408         {
409             get
410             {
411                 if (this.rootProperties != null)
412                 {
413                     return this.rootProperties.HasBeenAssociatedWithAnInstance;
414                 }
415                 else if (this.IsMetadataCached && this.RootActivity != null && this.RootActivity.rootProperties != null)
416                 {
417                     return this.RootActivity.rootProperties.HasBeenAssociatedWithAnInstance;
418                 }
419                 else
420                 {
421                     return false;
422                 }
423             }
424             set
425             {
426                 Fx.Assert(this.rootProperties != null, "This should only be called on the root and we should already be cached.");
427                 Fx.Assert(value, "We really only let you set this to true.");
428 
429                 this.rootProperties.HasBeenAssociatedWithAnInstance = value;
430             }
431         }
432 
433         internal Dictionary<string, List<RuntimeArgument>> OverloadGroups
434         {
435             get
436             {
437                 Fx.Assert(this.rootProperties != null || System.Diagnostics.Debugger.IsAttached, "This should only be called on the root.");
438                 return this.rootProperties.OverloadGroups;
439             }
440             set
441             {
442                 Fx.Assert(this.rootProperties != null, "This should only be called on the root.");
443                 this.rootProperties.OverloadGroups = value;
444             }
445         }
446 
447         internal List<RuntimeArgument> RequiredArgumentsNotInOverloadGroups
448         {
449             get
450             {
451                 Fx.Assert(this.rootProperties != null || System.Diagnostics.Debugger.IsAttached, "This should only be called on the root.");
452                 return this.rootProperties.RequiredArgumentsNotInOverloadGroups;
453             }
454             set
455             {
456                 Fx.Assert(this.rootProperties != null, "This should only be called on the root.");
457                 this.rootProperties.RequiredArgumentsNotInOverloadGroups = value;
458             }
459         }
460 
461         internal ValidationHelper.OverloadGroupEquivalenceInfo EquivalenceInfo
462         {
463             get
464             {
465                 Fx.Assert(this.rootProperties != null || System.Diagnostics.Debugger.IsAttached, "This should only be called on the root.");
466                 return this.rootProperties.EquivalenceInfo;
467             }
468             set
469             {
470                 Fx.Assert(this.rootProperties != null, "This should only be called on the root.");
471                 this.rootProperties.EquivalenceInfo = value;
472             }
473         }
474 
475         internal IList<Variable> RuntimeVariables
476         {
477             get
478             {
479                 return this.variables;
480             }
481         }
482 
483         internal IList<Variable> ImplementationVariables
484         {
485             get
486             {
487                 return this.implementationVariables;
488             }
489         }
490 
491         internal IList<Constraint> RuntimeConstraints
492         {
493             get
494             {
495                 return InternalGetConstraints();
496             }
497         }
498 
499         internal LocationReferenceEnvironment PublicEnvironment
500         {
501             get;
502             set;
503         }
504 
505         internal LocationReferenceEnvironment ImplementationEnvironment
506         {
507             get;
508             set;
509         }
510 
511         internal virtual bool InternalCanInduceIdle
512         {
513             get
514             {
515                 return false;
516             }
517         }
518 
519         internal bool HasTempViolations
520         {
521             get
522             {
523                 return (this.tempValidationErrors != null && this.tempValidationErrors.Count > 0);
524             }
525         }
526 
527         internal object ThisLock
528         {
529             get
530             {
531                 return this.thisLock;
532             }
533         }
534 
535         internal int RequiredExtensionTypesCount
536         {
537             get
538             {
539                 Fx.Assert(this.rootProperties != null || System.Diagnostics.Debugger.IsAttached, "only callable on the root");
540                 return this.rootProperties.RequiredExtensionTypesCount;
541             }
542         }
543 
544         internal int DefaultExtensionsCount
545         {
546             get
547             {
548                 Fx.Assert(this.rootProperties != null || System.Diagnostics.Debugger.IsAttached, "only callable on the root");
549                 return this.rootProperties.DefaultExtensionsCount;
550             }
551         }
552 
GetActivityExtensionInformation(out Dictionary<Type, WorkflowInstanceExtensionProvider> activityExtensionProviders, out HashSet<Type> requiredActivityExtensionTypes)553         internal bool GetActivityExtensionInformation(out Dictionary<Type, WorkflowInstanceExtensionProvider> activityExtensionProviders, out HashSet<Type> requiredActivityExtensionTypes)
554         {
555             Fx.Assert(this.rootProperties != null, "only callable on the root");
556             return this.rootProperties.GetActivityExtensionInformation(out activityExtensionProviders, out requiredActivityExtensionTypes);
557         }
558 
IsResultArgument(RuntimeArgument argument)559         internal virtual bool IsResultArgument(RuntimeArgument argument)
560         {
561             return false;
562         }
563 
CanBeScheduledBy(Activity parent)564         internal bool CanBeScheduledBy(Activity parent)
565         {
566             // fast path if we're the sole (or first) child
567             if (object.ReferenceEquals(parent, this.Parent))
568             {
569                 return this.relationshipToParent == RelationshipType.ImplementationChild || this.relationshipToParent == RelationshipType.Child;
570             }
571             else
572             {
573                 return parent.Children.Contains(this) || parent.ImplementationChildren.Contains(this);
574             }
575         }
576 
ClearIdInfo()577         internal void ClearIdInfo()
578         {
579             if (this.ParentOf != null)
580             {
581                 this.ParentOf.Dispose();
582                 this.ParentOf = null;
583             }
584 
585             this.id = 0;
586             this.qualifiedId = null;
587         }
588 
589         // We use these Set methods rather than a setter on the property since
590         // we don't want to make it seem like setting these collections is the
591         // "normal" thing to do.  Only OnInternalCacheMetadata implementations
592         // should call these methods.
SetChildrenCollection(Collection<Activity> children)593         internal void SetChildrenCollection(Collection<Activity> children)
594         {
595             this.children = children;
596         }
597 
AddChild(Activity child)598         internal void AddChild(Activity child)
599         {
600             if (this.children == null)
601             {
602                 this.children = new Collection<Activity>();
603             }
604 
605             this.children.Add(child);
606         }
607 
SetImplementationChildrenCollection(Collection<Activity> implementationChildren)608         internal void SetImplementationChildrenCollection(Collection<Activity> implementationChildren)
609         {
610             this.implementationChildren = implementationChildren;
611         }
612 
AddImplementationChild(Activity implementationChild)613         internal void AddImplementationChild(Activity implementationChild)
614         {
615             if (this.implementationChildren == null)
616             {
617                 this.implementationChildren = new Collection<Activity>();
618             }
619 
620             this.implementationChildren.Add(implementationChild);
621         }
622 
SetImportedChildrenCollection(Collection<Activity> importedChildren)623         internal void SetImportedChildrenCollection(Collection<Activity> importedChildren)
624         {
625             this.importedChildren = importedChildren;
626         }
627 
AddImportedChild(Activity importedChild)628         internal void AddImportedChild(Activity importedChild)
629         {
630             if (this.importedChildren == null)
631             {
632                 this.importedChildren = new Collection<Activity>();
633             }
634 
635             this.importedChildren.Add(importedChild);
636         }
637 
SetDelegatesCollection(Collection<ActivityDelegate> delegates)638         internal void SetDelegatesCollection(Collection<ActivityDelegate> delegates)
639         {
640             this.delegates = delegates;
641         }
642 
AddDelegate(ActivityDelegate activityDelegate)643         internal void AddDelegate(ActivityDelegate activityDelegate)
644         {
645             if (this.delegates == null)
646             {
647                 this.delegates = new Collection<ActivityDelegate>();
648             }
649 
650             this.delegates.Add(activityDelegate);
651         }
652 
SetImplementationDelegatesCollection(Collection<ActivityDelegate> implementationDelegates)653         internal void SetImplementationDelegatesCollection(Collection<ActivityDelegate> implementationDelegates)
654         {
655             this.implementationDelegates = implementationDelegates;
656         }
657 
AddImplementationDelegate(ActivityDelegate implementationDelegate)658         internal void AddImplementationDelegate(ActivityDelegate implementationDelegate)
659         {
660             if (this.implementationDelegates == null)
661             {
662                 this.implementationDelegates = new Collection<ActivityDelegate>();
663             }
664 
665             this.implementationDelegates.Add(implementationDelegate);
666         }
667 
SetImportedDelegatesCollection(Collection<ActivityDelegate> importedDelegates)668         internal void SetImportedDelegatesCollection(Collection<ActivityDelegate> importedDelegates)
669         {
670             this.importedDelegates = importedDelegates;
671         }
672 
AddImportedDelegate(ActivityDelegate importedDelegate)673         internal void AddImportedDelegate(ActivityDelegate importedDelegate)
674         {
675             if (this.importedDelegates == null)
676             {
677                 this.importedDelegates = new Collection<ActivityDelegate>();
678             }
679 
680             this.importedDelegates.Add(importedDelegate);
681         }
682 
SetVariablesCollection(Collection<Variable> variables)683         internal void SetVariablesCollection(Collection<Variable> variables)
684         {
685             this.variables = variables;
686         }
687 
AddVariable(Variable variable)688         internal void AddVariable(Variable variable)
689         {
690             if (this.variables == null)
691             {
692                 this.variables = new Collection<Variable>();
693             }
694 
695             this.variables.Add(variable);
696         }
697 
SetImplementationVariablesCollection(Collection<Variable> implementationVariables)698         internal void SetImplementationVariablesCollection(Collection<Variable> implementationVariables)
699         {
700             this.implementationVariables = implementationVariables;
701         }
702 
AddImplementationVariable(Variable implementationVariable)703         internal void AddImplementationVariable(Variable implementationVariable)
704         {
705             if (this.implementationVariables == null)
706             {
707                 this.implementationVariables = new Collection<Variable>();
708             }
709 
710             this.implementationVariables.Add(implementationVariable);
711         }
712 
SetArgumentsCollection(Collection<RuntimeArgument> arguments, bool createEmptyBindings)713         internal void SetArgumentsCollection(Collection<RuntimeArgument> arguments, bool createEmptyBindings)
714         {
715             this.arguments = arguments;
716 
717             // Arguments should always be "as bound as possible"
718             if (this.arguments != null && this.arguments.Count > 0)
719             {
720                 for (int i = 0; i < this.arguments.Count; i++)
721                 {
722                     RuntimeArgument argument = this.arguments[i];
723 
724                     argument.SetupBinding(this, createEmptyBindings);
725                 }
726 
727                 this.arguments.QuickSort(RuntimeArgument.EvaluationOrderComparer);
728             }
729         }
730 
AddArgument(RuntimeArgument argument, bool createEmptyBindings)731         internal void AddArgument(RuntimeArgument argument, bool createEmptyBindings)
732         {
733             if (this.arguments == null)
734             {
735                 this.arguments = new Collection<RuntimeArgument>();
736             }
737 
738             argument.SetupBinding(this, createEmptyBindings);
739 
740             int insertionIndex = this.arguments.BinarySearch(argument, RuntimeArgument.EvaluationOrderComparer);
741             if (insertionIndex < 0)
742             {
743                 this.arguments.Insert(~insertionIndex, argument);
744             }
745             else
746             {
747                 this.arguments.Insert(insertionIndex, argument);
748             }
749         }
750 
SetTempValidationErrorCollection(IList<ValidationError> validationErrors)751         internal void SetTempValidationErrorCollection(IList<ValidationError> validationErrors)
752         {
753             this.tempValidationErrors = validationErrors;
754         }
755 
TransferTempValidationErrors(ref IList<ValidationError> newList)756         internal void TransferTempValidationErrors(ref IList<ValidationError> newList)
757         {
758             if (this.tempValidationErrors != null)
759             {
760                 for (int i = 0; i < this.tempValidationErrors.Count; i++)
761                 {
762                     ActivityUtilities.Add(ref newList, this.tempValidationErrors[i]);
763                 }
764             }
765             this.tempValidationErrors = null;
766 
767         }
768 
AddTempValidationError(ValidationError validationError)769         internal void AddTempValidationError(ValidationError validationError)
770         {
771             if (this.tempValidationErrors == null)
772             {
773                 this.tempValidationErrors = new Collection<ValidationError>();
774             }
775 
776             this.tempValidationErrors.Add(validationError);
777         }
778 
AddTempAutoGeneratedArgument(Type argumentType, ArgumentDirection direction)779         internal RuntimeArgument AddTempAutoGeneratedArgument(Type argumentType, ArgumentDirection direction)
780         {
781             if (this.tempAutoGeneratedArguments == null)
782             {
783                 this.tempAutoGeneratedArguments = new Collection<RuntimeArgument>();
784             }
785 
786             string name = generatedArgumentPrefix + this.tempAutoGeneratedArguments.Count.ToString(CultureInfo.InvariantCulture);
787             RuntimeArgument argument = new RuntimeArgument(name, argumentType, direction);
788             this.tempAutoGeneratedArguments.Add(argument);
789             return argument;
790         }
791 
ResetTempAutoGeneratedArguments()792         internal void ResetTempAutoGeneratedArguments()
793         {
794             this.tempAutoGeneratedArguments = null;
795         }
796 
InternalGetConstraints()797         internal virtual IList<Constraint> InternalGetConstraints()
798         {
799             if (this.constraints != null && this.constraints.Count > 0)
800             {
801                 return this.constraints;
802             }
803             else
804             {
805                 return Activity.EmptyConstraints;
806             }
807         }
808 
NullCheck(T obj)809         internal static bool NullCheck<T>(T obj)
810         {
811             return (obj == null);
812         }
813 
ToString()814         public override string ToString()
815         {
816             return string.Format(CultureInfo.CurrentCulture, "{0}: {1}", this.Id, this.DisplayName);
817         }
818 
819         [EditorBrowsable(EditorBrowsableState.Never)]
ShouldSerializeDisplayName()820         public bool ShouldSerializeDisplayName()
821         {
822             return this.isDisplayNameSet;
823         }
824 
825         // subclasses are responsible for creating/disposing the necessary contexts
InternalAbort(ActivityInstance instance, ActivityExecutor executor, Exception terminationReason)826         internal virtual void InternalAbort(ActivityInstance instance, ActivityExecutor executor, Exception terminationReason)
827         {
828         }
829 
830         // subclasses are responsible for creating/disposing the necessary contexts
InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)831         internal virtual void InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
832         {
833             if (this.runtimeImplementation != null)
834             {
835                 executor.ScheduleActivity(this.runtimeImplementation, instance, null, null, null);
836             }
837         }
838 
839         // subclasses are responsible for creating/disposing the necessary contexts. This implementation
840         // covers Activity, Activity<T>, DynamicActivity, DynamicActivity<T>
InternalCancel(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)841         internal virtual void InternalCancel(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
842         {
843             NativeActivityContext context = executor.NativeActivityContextPool.Acquire();
844             try
845             {
846                 context.Initialize(instance, executor, bookmarkManager);
847                 context.Cancel();
848             }
849             finally
850             {
851                 context.Dispose();
852                 executor.NativeActivityContextPool.Release(context);
853             }
854         }
855 
IsSingletonActivityDeclared(string name)856         internal bool IsSingletonActivityDeclared(string name)
857         {
858             if (this.rootActivity == null || this.rootActivity.rootProperties == null)
859             {
860                 return false;
861             }
862             else
863             {
864                 return this.rootActivity.rootProperties.IsSingletonActivityDeclared(name);
865             }
866         }
867 
DeclareSingletonActivity(string name, Activity activity)868         internal void DeclareSingletonActivity(string name, Activity activity)
869         {
870             if (this.rootActivity != null && this.rootActivity.rootProperties != null)
871             {
872                 this.rootActivity.rootProperties.DeclareSingletonActivity(name, activity);
873             }
874         }
875 
GetSingletonActivity(string name)876         internal Activity GetSingletonActivity(string name)
877         {
878             if (this.rootActivity != null && this.rootActivity.rootProperties != null)
879             {
880                 return this.rootActivity.rootProperties.GetSingletonActivity(name);
881             }
882 
883             return null;
884         }
885 
ClearCachedInformation()886         internal void ClearCachedInformation()
887         {
888             ClearCachedMetadata();
889             this.isMetadataCached = CacheStates.Uncached;
890         }
891 
InitializeAsRoot(LocationReferenceEnvironment hostEnvironment)892         internal void InitializeAsRoot(LocationReferenceEnvironment hostEnvironment)
893         {
894             // We're being treated as the root of the workflow
895             this.Parent = null;
896             this.ParentOf = null;
897 
898             Interlocked.CompareExchange(ref nextCacheId, 1, int.MaxValue);
899             this.cacheId = Interlocked.Increment(ref nextCacheId);
900 
901             ClearCachedInformation();
902 
903             this.MemberOf = new IdSpace();
904             this.rootProperties = new RootProperties();
905             this.rootProperties.HostEnvironment = hostEnvironment;
906             this.rootActivity = this;
907         }
908 
GetParentEnvironment()909         internal LocationReferenceEnvironment GetParentEnvironment()
910         {
911             LocationReferenceEnvironment parentEnvironment = null;
912 
913             if (this.Parent == null)
914             {
915                 Fx.Assert(this.rootProperties != null, "Root properties must be available now.");
916 
917                 parentEnvironment = new ActivityLocationReferenceEnvironment(this.rootProperties.HostEnvironment) { InternalRoot = this };
918             }
919             else
920             {
921                 switch (this.relationshipToParent)
922                 {
923                     case RelationshipType.ArgumentExpression:
924                         parentEnvironment = this.Parent.PublicEnvironment.Parent;
925 
926                         if (parentEnvironment == null)
927                         {
928                             parentEnvironment = this.RootActivity.rootProperties.HostEnvironment;
929                         }
930                         break;
931                     case RelationshipType.DelegateHandler:
932                         Fx.Assert(this.HandlerOf != null, "Must have the parent delegate set");
933 
934                         parentEnvironment = this.HandlerOf.Environment;
935                         break;
936                     case RelationshipType.Child:
937                     case RelationshipType.ImportedChild:
938                     case RelationshipType.VariableDefault:
939                         parentEnvironment = this.Parent.PublicEnvironment;
940                         break;
941                     case RelationshipType.ImplementationChild:
942                         parentEnvironment = this.Parent.ImplementationEnvironment;
943                         break;
944                 }
945             }
946 
947             return parentEnvironment;
948         }
949 
InitializeRelationship(ActivityDelegate activityDelegate, ActivityCollectionType collectionType, ref IList<ValidationError> validationErrors)950         internal bool InitializeRelationship(ActivityDelegate activityDelegate, ActivityCollectionType collectionType, ref IList<ValidationError> validationErrors)
951         {
952             if (this.cacheId == activityDelegate.Owner.CacheId)
953             {
954                 // This means that we already have a parent and a delegate is trying to initialize
955                 // a relationship.  Delegate handlers MUST be declared.
956 
957                 ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.ActivityDelegateHandlersMustBeDeclarations(this.DisplayName, activityDelegate.Owner.DisplayName, this.Parent.DisplayName), false, activityDelegate.Owner));
958 
959                 return false;
960             }
961 
962             if (InitializeRelationship(activityDelegate.Owner, collectionType != ActivityCollectionType.Implementation, RelationshipType.DelegateHandler, ref validationErrors))
963             {
964                 this.HandlerOf = activityDelegate;
965 
966                 return true;
967             }
968 
969             return false;
970         }
971 
InitializeRelationship(RuntimeArgument argument, ref IList<ValidationError> validationErrors)972         internal bool InitializeRelationship(RuntimeArgument argument, ref IList<ValidationError> validationErrors)
973         {
974             return InitializeRelationship(argument.Owner, true, RelationshipType.ArgumentExpression, ref validationErrors);
975         }
976 
InitializeRelationship(Variable variable, bool isPublic, ref IList<ValidationError> validationErrors)977         internal bool InitializeRelationship(Variable variable, bool isPublic, ref IList<ValidationError> validationErrors)
978         {
979             return InitializeRelationship(variable.Owner, isPublic, RelationshipType.VariableDefault, ref validationErrors);
980         }
981 
InitializeRelationship(Activity parent, ActivityCollectionType collectionType, ref IList<ValidationError> validationErrors)982         internal bool InitializeRelationship(Activity parent, ActivityCollectionType collectionType, ref IList<ValidationError> validationErrors)
983         {
984             RelationshipType relationshipType = RelationshipType.Child;
985             if (collectionType == ActivityCollectionType.Imports)
986             {
987                 relationshipType = RelationshipType.ImportedChild;
988             }
989             else if (collectionType == ActivityCollectionType.Implementation)
990             {
991                 relationshipType = RelationshipType.ImplementationChild;
992             }
993 
994             return InitializeRelationship(parent, collectionType != ActivityCollectionType.Implementation, relationshipType, ref validationErrors);
995         }
996 
InitializeRelationship(Activity parent, bool isPublic, RelationshipType relationship, ref IList<ValidationError> validationErrors)997         bool InitializeRelationship(Activity parent, bool isPublic, RelationshipType relationship, ref IList<ValidationError> validationErrors)
998         {
999             if (this.cacheId == parent.cacheId)
1000             {
1001                 // This means that we've already encountered a parent in the tree
1002 
1003                 // Validate that it is visible.
1004 
1005                 // In order to see the activity the new parent must be
1006                 // in the implementation IdSpace of an activity which has
1007                 // a public reference to it.
1008                 Activity referenceTarget = parent.MemberOf.Owner;
1009 
1010                 if (object.ReferenceEquals(this, parent))
1011                 {
1012                     ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.ActivityCannotReferenceItself(this.DisplayName), parent));
1013 
1014                     return false;
1015                 }
1016                 else if (this.Parent == null)
1017                 {
1018                     ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.RootActivityCannotBeReferenced(this.DisplayName, parent.DisplayName), parent));
1019 
1020                     return false;
1021                 }
1022                 else if (referenceTarget == null)
1023                 {
1024                     ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.ActivityCannotBeReferencedWithoutTarget(this.DisplayName, parent.DisplayName, this.Parent.DisplayName), parent));
1025 
1026                     return false;
1027                 }
1028                 else if (!referenceTarget.Children.Contains(this) && !referenceTarget.ImportedChildren.Contains(this))
1029                 {
1030                     ActivityUtilities.Add(ref validationErrors, new ValidationError(SR.ActivityCannotBeReferenced(this.DisplayName, parent.DisplayName, referenceTarget.DisplayName, this.Parent.DisplayName), false, parent));
1031 
1032                     return false;
1033                 }
1034 
1035                 // This is a valid reference so we want to allow
1036                 // normal processing to proceed.
1037                 return true;
1038             }
1039 
1040             this.Parent = parent;
1041             this.HandlerOf = null;
1042             this.rootActivity = parent.RootActivity;
1043             this.cacheId = parent.cacheId;
1044             this.isMetadataCached = CacheStates.Uncached;
1045             ClearCachedMetadata();
1046             this.relationshipToParent = relationship;
1047 
1048             if (isPublic)
1049             {
1050                 this.MemberOf = parent.MemberOf;
1051             }
1052             else
1053             {
1054                 if (parent.ParentOf == null)
1055                 {
1056                     parent.ParentOf = new IdSpace(parent.MemberOf, parent.InternalId);
1057                 }
1058 
1059                 this.MemberOf = parent.ParentOf;
1060             }
1061 
1062             return true;
1063         }
1064 
ClearCachedMetadata()1065         void ClearCachedMetadata()
1066         {
1067             this.symbolCount = 0;
1068 
1069             this.arguments = null;
1070 
1071             this.children = null;
1072             this.implementationChildren = null;
1073             this.importedChildren = null;
1074 
1075             this.delegates = null;
1076             this.implementationDelegates = null;
1077             this.importedDelegates = null;
1078 
1079             this.variables = null;
1080             this.implementationVariables = null;
1081         }
1082 
InternalCacheMetadata(bool createEmptyBindings, ref IList<ValidationError> validationErrors)1083         internal void InternalCacheMetadata(bool createEmptyBindings, ref IList<ValidationError> validationErrors)
1084         {
1085             OnInternalCacheMetadata(createEmptyBindings);
1086 
1087             if (this.tempAutoGeneratedArguments != null)
1088             {
1089                 Fx.Assert(this.tempAutoGeneratedArguments.Count > 0, "We should only have a non-null value here if we generated an argument");
1090                 if (!this.SkipArgumentResolution)
1091                 {
1092                     ActivityUtilities.Add(ref validationErrors, new ValidationError(
1093                         SR.PublicReferencesOnActivityRequiringArgumentResolution(this.DisplayName), false, this));
1094                 }
1095 
1096                 if (this.arguments == null)
1097                 {
1098                     this.arguments = this.tempAutoGeneratedArguments;
1099                 }
1100                 else
1101                 {
1102                     for (int i = 0; i < this.tempAutoGeneratedArguments.Count; i++)
1103                     {
1104                         this.arguments.Add(this.tempAutoGeneratedArguments[i]);
1105                     }
1106                 }
1107 
1108                 this.tempAutoGeneratedArguments = null;
1109             }
1110 
1111             if (this.arguments != null && this.arguments.Count > 1)
1112             {
1113                 ActivityValidationServices.ValidateEvaluationOrder(this.arguments, this, ref this.tempValidationErrors);
1114             }
1115 
1116             if (this.tempValidationErrors != null)
1117             {
1118                 if (validationErrors == null)
1119                 {
1120                     validationErrors = new List<ValidationError>();
1121                 }
1122 
1123                 for (int i = 0; i < this.tempValidationErrors.Count; i++)
1124                 {
1125                     ValidationError validationError = this.tempValidationErrors[i];
1126 
1127                     validationError.Source = this;
1128                     validationError.Id = this.Id;
1129 
1130                     validationErrors.Add(validationError);
1131                 }
1132 
1133                 this.tempValidationErrors = null;
1134             }
1135 
1136             if (this.arguments == null)
1137             {
1138                 this.arguments = emptyArguments;
1139             }
1140             else
1141             {
1142                 this.symbolCount += this.arguments.Count;
1143             }
1144 
1145             if (this.variables == null)
1146             {
1147                 this.variables = emptyVariables;
1148             }
1149             else
1150             {
1151                 this.symbolCount += this.variables.Count;
1152             }
1153 
1154             if (this.implementationVariables == null)
1155             {
1156                 this.implementationVariables = emptyVariables;
1157             }
1158             else
1159             {
1160                 this.symbolCount += this.implementationVariables.Count;
1161             }
1162 
1163             if (this.children == null)
1164             {
1165                 this.children = emptyChildren;
1166             }
1167 
1168             if (this.importedChildren == null)
1169             {
1170                 this.importedChildren = emptyChildren;
1171             }
1172 
1173             if (this.implementationChildren == null)
1174             {
1175                 this.implementationChildren = emptyChildren;
1176             }
1177 
1178             if (this.delegates == null)
1179             {
1180                 this.delegates = emptyDelegates;
1181             }
1182 
1183             if (this.importedDelegates == null)
1184             {
1185                 this.importedDelegates = emptyDelegates;
1186             }
1187 
1188             if (this.implementationDelegates == null)
1189             {
1190                 this.implementationDelegates = emptyDelegates;
1191             }
1192 
1193             this.isMetadataCached = CacheStates.Partial;
1194         }
1195 
1196         // Note that this is relative to the type of walk we've done.  If we
1197         // skipped implementation then we can still be "Cached" even though
1198         // we never ignored the implementation.
SetCached(bool isSkippingPrivateChildren)1199         internal void SetCached(bool isSkippingPrivateChildren)
1200         {
1201             if (isSkippingPrivateChildren)
1202             {
1203                 this.isMetadataCached = CacheStates.Partial;
1204             }
1205             else
1206             {
1207                 this.isMetadataCached = CacheStates.Full;
1208             }
1209         }
1210 
SetRuntimeReady()1211         internal void SetRuntimeReady()
1212         {
1213             this.isMetadataCached |= CacheStates.RuntimeReady;
1214         }
1215 
OnInternalCacheMetadata(bool createEmptyBindings)1216         internal virtual void OnInternalCacheMetadata(bool createEmptyBindings)
1217         {
1218             // By running CacheMetadata first we allow the user
1219             // to set their Implementation during CacheMetadata.
1220             ActivityMetadata metadata = new ActivityMetadata(this, GetParentEnvironment(), createEmptyBindings);
1221             CacheMetadata(metadata);
1222             metadata.Dispose();
1223 
1224             if (this.Implementation != null)
1225             {
1226                 this.runtimeImplementation = this.Implementation();
1227             }
1228             else
1229             {
1230                 this.runtimeImplementation = null;
1231             }
1232 
1233             if (this.runtimeImplementation != null)
1234             {
1235                 SetImplementationChildrenCollection(new Collection<Activity>
1236                 {
1237                     this.runtimeImplementation
1238                 });
1239             }
1240         }
1241 
CacheMetadata(ActivityMetadata metadata)1242         protected virtual void CacheMetadata(ActivityMetadata metadata)
1243         {
1244             ReflectedInformation information = new ReflectedInformation(this);
1245 
1246             SetImportedChildrenCollection(information.GetChildren());
1247             SetVariablesCollection(information.GetVariables());
1248             SetImportedDelegatesCollection(information.GetDelegates());
1249             SetArgumentsCollection(information.GetArguments(), metadata.CreateEmptyBindings);
1250         }
1251 
OnInternalCreateDynamicUpdateMap(DynamicUpdateMapBuilder.Finalizer finalizer, DynamicUpdateMapBuilder.IDefinitionMatcher matcher, Activity originalActivity)1252         internal virtual void OnInternalCreateDynamicUpdateMap(DynamicUpdateMapBuilder.Finalizer finalizer,
1253             DynamicUpdateMapBuilder.IDefinitionMatcher matcher, Activity originalActivity)
1254         {
1255             UpdateMapMetadata metadata = new UpdateMapMetadata(finalizer, matcher, this);
1256             try
1257             {
1258                 OnCreateDynamicUpdateMap(metadata, originalActivity);
1259             }
1260             finally
1261             {
1262                 metadata.Dispose();
1263             }
1264         }
1265 
OnCreateDynamicUpdateMap(UpdateMapMetadata metadata, Activity originalActivity)1266         protected virtual void OnCreateDynamicUpdateMap(UpdateMapMetadata metadata, Activity originalActivity)
1267         {
1268         }
1269 
1270         internal void AddDefaultExtensionProvider<T>(Func<T> extensionProvider)
1271             where T : class
1272         {
1273             Fx.Assert(extensionProvider != null, "caller must verify");
1274             Fx.Assert(this.rootActivity != null && this.rootActivity.rootProperties != null, "need a valid root");
this.rootActivity.rootProperties.AddDefaultExtensionProvider(extensionProvider)1275             this.rootActivity.rootProperties.AddDefaultExtensionProvider(extensionProvider);
1276         }
1277 
RequireExtension(Type extensionType)1278         internal void RequireExtension(Type extensionType)
1279         {
1280             Fx.Assert(extensionType != null && !extensionType.IsValueType, "caller should verify we have a valid reference type");
1281             Fx.Assert(this.rootActivity != null && this.rootActivity.rootProperties != null, "need a valid root");
1282             this.rootActivity.rootProperties.RequireExtension(extensionType);
1283         }
1284 
1285         // information used by root activities
1286         class RootProperties
1287         {
1288             Dictionary<string, Activity> singletonActivityNames;
1289             Dictionary<Type, WorkflowInstanceExtensionProvider> activityExtensionProviders;
1290             HashSet<Type> requiredExtensionTypes;
1291 
RootProperties()1292             public RootProperties()
1293             {
1294             }
1295 
1296             public bool HasBeenAssociatedWithAnInstance
1297             {
1298                 get;
1299                 set;
1300             }
1301 
1302             public LocationReferenceEnvironment HostEnvironment
1303             {
1304                 get;
1305                 set;
1306             }
1307 
1308             public Dictionary<string, List<RuntimeArgument>> OverloadGroups
1309             {
1310                 get;
1311                 set;
1312             }
1313 
1314             public List<RuntimeArgument> RequiredArgumentsNotInOverloadGroups
1315             {
1316                 get;
1317                 set;
1318             }
1319 
1320             public ValidationHelper.OverloadGroupEquivalenceInfo EquivalenceInfo
1321             {
1322                 get;
1323                 set;
1324             }
1325 
1326             public int DefaultExtensionsCount
1327             {
1328                 get
1329                 {
1330                     if (this.activityExtensionProviders != null)
1331                     {
1332                         return this.activityExtensionProviders.Count;
1333                     }
1334                     else
1335                     {
1336                         return 0;
1337                     }
1338                 }
1339             }
1340 
1341             public int RequiredExtensionTypesCount
1342             {
1343                 get
1344                 {
1345                     if (this.requiredExtensionTypes != null)
1346                     {
1347                         return this.requiredExtensionTypes.Count;
1348                     }
1349                     else
1350                     {
1351                         return 0;
1352                     }
1353                 }
1354             }
1355 
GetActivityExtensionInformation(out Dictionary<Type, WorkflowInstanceExtensionProvider> activityExtensionProviders, out HashSet<Type> requiredActivityExtensionTypes)1356             public bool GetActivityExtensionInformation(out Dictionary<Type, WorkflowInstanceExtensionProvider> activityExtensionProviders, out HashSet<Type> requiredActivityExtensionTypes)
1357             {
1358                 activityExtensionProviders = this.activityExtensionProviders;
1359                 requiredActivityExtensionTypes = this.requiredExtensionTypes;
1360                 return activityExtensionProviders != null || (requiredExtensionTypes != null && requiredExtensionTypes.Count > 0);
1361             }
1362 
1363             public void AddDefaultExtensionProvider<T>(Func<T> extensionProvider)
1364                 where T : class
1365             {
1366                 Type key = typeof(T);
1367                 if (this.activityExtensionProviders == null)
1368                 {
1369                     this.activityExtensionProviders = new Dictionary<Type, WorkflowInstanceExtensionProvider>();
1370                 }
1371                 else
1372                 {
1373                     if (this.activityExtensionProviders.ContainsKey(key))
1374                     {
1375                         return; // already have a provider of this type
1376                     }
1377                 }
1378 
this.activityExtensionProviders.Add(key, new WorkflowInstanceExtensionProvider<T>(extensionProvider))1379                 this.activityExtensionProviders.Add(key, new WorkflowInstanceExtensionProvider<T>(extensionProvider));
1380 
1381                 // if we're providing an extension that exactly matches a required type, simplify further bookkeeping
1382                 if (this.requiredExtensionTypes != null)
1383                 {
1384                     this.requiredExtensionTypes.Remove(key);
1385                 }
1386             }
1387 
RequireExtension(Type extensionType)1388             public void RequireExtension(Type extensionType)
1389             {
1390                 // if we're providing an extension that exactly matches a required type, don't bother with further bookkeeping
1391                 if (this.activityExtensionProviders != null && this.activityExtensionProviders.ContainsKey(extensionType))
1392                 {
1393                     return;
1394                 }
1395 
1396                 if (this.requiredExtensionTypes == null)
1397                 {
1398                     this.requiredExtensionTypes = new HashSet<Type>();
1399                 }
1400                 this.requiredExtensionTypes.Add(extensionType);
1401             }
1402 
IsSingletonActivityDeclared(string name)1403             public bool IsSingletonActivityDeclared(string name)
1404             {
1405                 if (this.singletonActivityNames == null)
1406                 {
1407                     return false;
1408                 }
1409                 else
1410                 {
1411                     return this.singletonActivityNames.ContainsKey(name);
1412                 }
1413             }
1414 
DeclareSingletonActivity(string name, Activity activity)1415             public void DeclareSingletonActivity(string name, Activity activity)
1416             {
1417                 if (this.singletonActivityNames == null)
1418                 {
1419                     this.singletonActivityNames = new Dictionary<string, Activity>(1);
1420                 }
1421 
1422                 this.singletonActivityNames.Add(name, activity);
1423             }
1424 
GetSingletonActivity(string name)1425             public Activity GetSingletonActivity(string name)
1426             {
1427                 Activity result = null;
1428                 if (this.singletonActivityNames != null)
1429                 {
1430                     this.singletonActivityNames.TryGetValue(name, out result);
1431                 }
1432 
1433                 return result;
1434             }
1435         }
1436 
1437         internal class ReflectedInformation
1438         {
1439             Activity parent;
1440 
1441             Collection<RuntimeArgument> arguments;
1442             Collection<Variable> variables;
1443             Collection<Activity> children;
1444             Collection<ActivityDelegate> delegates;
1445 
1446             static Type DictionaryArgumentHelperType = typeof(DictionaryArgumentHelper<>);
1447             static Type OverloadGroupAttributeType = typeof(OverloadGroupAttribute);
1448 
ReflectedInformation(Activity owner)1449             public ReflectedInformation(Activity owner)
1450                 : this(owner, ReflectedType.All)
1451             {
1452             }
1453 
ReflectedInformation(Activity activity, ReflectedType reflectType)1454             ReflectedInformation(Activity activity, ReflectedType reflectType)
1455             {
1456                 this.parent = activity;
1457 
1458                 // reflect over our activity and gather relevant pieces of the system so that the developer
1459                 // doesn't need to worry about "zipping up" his model to the constructs necessary for the
1460                 // runtime to function correctly
1461                 foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(activity))
1462                 {
1463                     ArgumentDirection direction;
1464                     Type argumentType;
1465                     if ((reflectType & ReflectedType.Argument) == ReflectedType.Argument &&
1466                         ActivityUtilities.TryGetArgumentDirectionAndType(propertyDescriptor.PropertyType, out direction, out argumentType))
1467                     {
1468                         // We only do our magic for generic argument types.  If the property is a non-generic
1469                         // argument type then that means the type of the RuntimeArgument should be based on
1470                         // the type of the argument bound to it.  The activity author is responsible for dealing
1471                         // with these dynamic typing cases.
1472                         if (propertyDescriptor.PropertyType.IsGenericType)
1473                         {
1474                             bool isRequired = GetIsArgumentRequired(propertyDescriptor);
1475                             List<string> overloadGroupNames = GetOverloadGroupNames(propertyDescriptor);
1476                             RuntimeArgument argument = new RuntimeArgument(propertyDescriptor.Name, argumentType, direction, isRequired, overloadGroupNames, propertyDescriptor, activity);
1477                             Add<RuntimeArgument>(ref this.arguments, argument);
1478                         }
1479                     }
1480                     else if ((reflectType & ReflectedType.Variable) == ReflectedType.Variable &&
1481                         ActivityUtilities.IsVariableType(propertyDescriptor.PropertyType))
1482                     {
1483                         Variable variable = propertyDescriptor.GetValue(activity) as Variable;
1484                         if (variable != null)
1485                         {
1486                             Add<Variable>(ref this.variables, variable);
1487                         }
1488                     }
1489                     else if ((reflectType & ReflectedType.Child) == ReflectedType.Child &&
1490                         ActivityUtilities.IsActivityType(propertyDescriptor.PropertyType))
1491                     {
1492                         Activity workflowElement = propertyDescriptor.GetValue(activity) as Activity;
1493                         Add<Activity>(ref this.children, workflowElement);
1494                     }
1495                     else if ((reflectType & ReflectedType.ActivityDelegate) == ReflectedType.ActivityDelegate &&
1496                         ActivityUtilities.IsActivityDelegateType(propertyDescriptor.PropertyType))
1497                     {
1498                         ActivityDelegate activityDelegate = propertyDescriptor.GetValue(activity) as ActivityDelegate;
1499                         Add<ActivityDelegate>(ref this.delegates, activityDelegate);
1500                     }
1501                     else
1502                     {
1503                         Type innerType;
1504                         bool foundMatch = false;
1505                         if ((reflectType & ReflectedType.Argument) == ReflectedType.Argument)
1506                         {
1507                             object property = propertyDescriptor.GetValue(activity);
1508                             if (property != null)
1509                             {
1510                                 IList<RuntimeArgument> runtimeArguments = DictionaryArgumentHelper.TryGetRuntimeArguments(property, propertyDescriptor.Name);
1511                                 if (runtimeArguments != null)
1512                                 {
1513                                     this.AddCollection(ref this.arguments, runtimeArguments);
1514                                     foundMatch = true;
1515                                 }
1516                                 else if (ActivityUtilities.IsArgumentDictionaryType(propertyDescriptor.PropertyType, out innerType))
1517                                 {
1518                                     Type concreteHelperType = DictionaryArgumentHelperType.MakeGenericType(innerType);
1519                                     DictionaryArgumentHelper helper = Activator.CreateInstance(concreteHelperType, new object[] { property, propertyDescriptor.Name }) as DictionaryArgumentHelper;
1520                                     this.AddCollection(ref this.arguments, helper.RuntimeArguments);
1521                                     foundMatch = true;
1522                                 }
1523                             }
1524                         }
1525 
1526                         if (!foundMatch && ActivityUtilities.IsKnownCollectionType(propertyDescriptor.PropertyType, out innerType))
1527                         {
1528                             if ((reflectType & ReflectedType.Variable) == ReflectedType.Variable &&
1529                                 ActivityUtilities.IsVariableType(innerType))
1530                             {
1531                                 IEnumerable enumerable = propertyDescriptor.GetValue(activity) as IEnumerable;
1532 
1533                                 AddCollection(ref this.variables, enumerable);
1534                             }
1535                             else if ((reflectType & ReflectedType.Child) == ReflectedType.Child &&
1536                                 ActivityUtilities.IsActivityType(innerType, false))
1537                             {
1538                                 IEnumerable enumerable = propertyDescriptor.GetValue(activity) as IEnumerable;
1539 
1540                                 AddCollection(ref this.children, enumerable);
1541                             }
1542                             else if ((reflectType & ReflectedType.ActivityDelegate) == ReflectedType.ActivityDelegate &&
1543                                 ActivityUtilities.IsActivityDelegateType(innerType))
1544                             {
1545                                 IEnumerable enumerable = propertyDescriptor.GetValue(activity) as IEnumerable;
1546 
1547                                 AddCollection(ref this.delegates, enumerable);
1548                             }
1549                         }
1550                     }
1551                 }
1552             }
1553 
GetArguments(Activity parent)1554             public static Collection<RuntimeArgument> GetArguments(Activity parent)
1555             {
1556                 Collection<RuntimeArgument> arguments = null;
1557 
1558                 if (parent != null)
1559                 {
1560                     arguments = new ReflectedInformation(parent, ReflectedType.Argument).GetArguments();
1561                 }
1562 
1563                 if (arguments == null)
1564                 {
1565                     arguments = new Collection<RuntimeArgument>();
1566                 }
1567 
1568                 return arguments;
1569             }
1570 
GetVariables(Activity parent)1571             public static Collection<Variable> GetVariables(Activity parent)
1572             {
1573                 Collection<Variable> variables = null;
1574 
1575                 if (parent != null)
1576                 {
1577                     variables = new ReflectedInformation(parent, ReflectedType.Variable).GetVariables();
1578                 }
1579 
1580                 if (variables == null)
1581                 {
1582                     variables = new Collection<Variable>();
1583                 }
1584 
1585                 return variables;
1586             }
1587 
GetChildren(Activity parent)1588             public static Collection<Activity> GetChildren(Activity parent)
1589             {
1590                 Collection<Activity> children = null;
1591 
1592                 if (parent != null)
1593                 {
1594                     children = new ReflectedInformation(parent, ReflectedType.Child).GetChildren();
1595                 }
1596 
1597                 if (children == null)
1598                 {
1599                     children = new Collection<Activity>();
1600                 }
1601 
1602                 return children;
1603             }
1604 
GetDelegates(Activity parent)1605             public static Collection<ActivityDelegate> GetDelegates(Activity parent)
1606             {
1607                 Collection<ActivityDelegate> delegates = null;
1608 
1609                 if (parent != null)
1610                 {
1611                     delegates = new ReflectedInformation(parent, ReflectedType.ActivityDelegate).GetDelegates();
1612                 }
1613 
1614                 if (delegates == null)
1615                 {
1616                     delegates = new Collection<ActivityDelegate>();
1617                 }
1618 
1619                 return delegates;
1620             }
1621 
GetArguments()1622             public Collection<RuntimeArgument> GetArguments()
1623             {
1624                 return this.arguments;
1625             }
1626 
GetVariables()1627             public Collection<Variable> GetVariables()
1628             {
1629                 return this.variables;
1630             }
1631 
GetChildren()1632             public Collection<Activity> GetChildren()
1633             {
1634                 return this.children;
1635             }
1636 
GetDelegates()1637             public Collection<ActivityDelegate> GetDelegates()
1638             {
1639                 return this.delegates;
1640             }
1641 
1642             void AddCollection<T>(ref Collection<T> list, IEnumerable enumerable)
1643                 where T : class
1644             {
1645                 if (enumerable != null)
1646                 {
1647                     foreach (object obj in enumerable)
1648                     {
1649                         if (obj != null && obj is T)
1650                         {
1651                             Add<T>(ref list, (T)obj);
1652                         }
1653                     }
1654                 }
1655             }
1656 
Add(ref Collection<T> list, T data)1657             void Add<T>(ref Collection<T> list, T data)
1658             {
1659                 if (data != null)
1660                 {
1661                     if (list == null)
1662                     {
1663                         list = new Collection<T>();
1664                     }
1665                     list.Add(data);
1666                 }
1667             }
1668 
GetIsArgumentRequired(PropertyDescriptor propertyDescriptor)1669             bool GetIsArgumentRequired(PropertyDescriptor propertyDescriptor)
1670             {
1671                 return propertyDescriptor.Attributes[typeof(RequiredArgumentAttribute)] != null;
1672             }
1673 
GetOverloadGroupNames(PropertyDescriptor propertyDescriptor)1674             List<string> GetOverloadGroupNames(PropertyDescriptor propertyDescriptor)
1675             {
1676                 List<string> overloadGroupNames = new List<string>(0);
1677                 AttributeCollection propertyAttributes = propertyDescriptor.Attributes;
1678                 for (int i = 0; i < propertyAttributes.Count; i++)
1679                 {
1680                     Attribute attribute = propertyAttributes[i];
1681                     if (ReflectedInformation.OverloadGroupAttributeType.IsAssignableFrom(attribute.GetType()))
1682                     {
1683                         overloadGroupNames.Add(((OverloadGroupAttribute)attribute).GroupName);
1684                     }
1685                 }
1686                 return overloadGroupNames;
1687             }
1688 
1689             [Flags]
1690             enum ReflectedType
1691             {
1692                 Argument = 0X1,
1693                 Variable = 0X2,
1694                 Child = 0X4,
1695                 ActivityDelegate = 0X8,
1696                 All = 0XF
1697             }
1698 
1699             class DictionaryArgumentHelper
1700             {
DictionaryArgumentHelper()1701                 protected DictionaryArgumentHelper()
1702                 {
1703                 }
1704 
1705                 public IList<RuntimeArgument> RuntimeArguments
1706                 {
1707                     get;
1708                     protected set;
1709                 }
1710 
TryGetRuntimeArguments(object propertyValue, string propertyName)1711                 public static IList<RuntimeArgument> TryGetRuntimeArguments(object propertyValue, string propertyName)
1712                 {
1713                     // special case each of the non-generic argument types to avoid reflection costs
1714 
1715                     IEnumerable<KeyValuePair<string, Argument>> argumentEnumerable = propertyValue as IEnumerable<KeyValuePair<string, Argument>>;
1716                     if (argumentEnumerable != null)
1717                     {
1718                         return GetRuntimeArguments(argumentEnumerable, propertyName);
1719                     }
1720 
1721                     IEnumerable<KeyValuePair<string, InArgument>> inArgumentEnumerable = propertyValue as IEnumerable<KeyValuePair<string, InArgument>>;
1722                     if (inArgumentEnumerable != null)
1723                     {
1724                         return GetRuntimeArguments(inArgumentEnumerable, propertyName);
1725                     }
1726 
1727                     IEnumerable<KeyValuePair<string, OutArgument>> outArgumentEnumerable = propertyValue as IEnumerable<KeyValuePair<string, OutArgument>>;
1728                     if (outArgumentEnumerable != null)
1729                     {
1730                         return GetRuntimeArguments(outArgumentEnumerable, propertyName);
1731                     }
1732 
1733                     IEnumerable<KeyValuePair<string, InOutArgument>> inOutArgumentEnumerable = propertyValue as IEnumerable<KeyValuePair<string, InOutArgument>>;
1734                     if (inOutArgumentEnumerable != null)
1735                     {
1736                         return GetRuntimeArguments(inOutArgumentEnumerable, propertyName);
1737                     }
1738 
1739                     return null;
1740                 }
1741 
1742                 protected static IList<RuntimeArgument> GetRuntimeArguments<T>(IEnumerable<KeyValuePair<string, T>> argumentDictionary, string propertyName) where T : Argument
1743                 {
1744                     IList<RuntimeArgument> runtimeArguments = new List<RuntimeArgument>();
1745 
1746                     foreach (KeyValuePair<string, T> pair in argumentDictionary)
1747                     {
1748                         string key = pair.Key;
1749                         Argument value = pair.Value;
1750 
1751                         if (value == null)
1752                         {
1753                             string argName = (key == null) ? "<null>" : key;
1754                             throw FxTrace.Exception.AsError(new ValidationException(SR.MissingArgument(argName, propertyName)));
1755                         }
1756                         if (string.IsNullOrEmpty(key))
1757                         {
1758                             throw FxTrace.Exception.AsError(new ValidationException(SR.MissingNameProperty(value.ArgumentType)));
1759                         }
1760 
1761                         RuntimeArgument runtimeArgument = new RuntimeArgument(key, value.ArgumentType, value.Direction, false, null, value);
1762                         runtimeArguments.Add(runtimeArgument);
1763                     }
1764 
1765                     return runtimeArguments;
1766                 }
1767             }
1768 
1769             class DictionaryArgumentHelper<T> : DictionaryArgumentHelper where T : Argument
1770             {
DictionaryArgumentHelper(object propertyValue, string propertyName)1771                 public DictionaryArgumentHelper(object propertyValue, string propertyName)
1772                     : base()
1773                 {
1774                     IEnumerable<KeyValuePair<string, T>> argumentDictionary = propertyValue as IEnumerable<KeyValuePair<string, T>>;
1775 
1776                     this.RuntimeArguments = GetRuntimeArguments(argumentDictionary, propertyName);
1777                 }
1778             }
1779 
1780         }
1781 
1782         internal enum RelationshipType : byte
1783         {
1784             Child = 0x00,
1785             ImportedChild = 0x01,
1786             ImplementationChild = 0x02,
1787             DelegateHandler = 0x03,
1788             ArgumentExpression = 0x04,
1789             VariableDefault = 0x05
1790         }
1791 
1792         enum CacheStates : byte
1793         {
1794             // We don't have valid cached data
1795             Uncached = 0x00,
1796 
1797             // The next two states are mutually exclusive:
1798 
1799             // The activity has its own metadata cached, or private implementation are skipped
1800             Partial = 0x01,
1801 
1802             // The activity has its own metadata and its private implementation cached
1803             // We can make use of the roll-up metadata (like
1804             // SubtreeHasConstraints).
1805             Full = 0x02,
1806 
1807             // The next state can be ORed with the last two:
1808 
1809             // The cached data is ready for runtime use
1810             RuntimeReady = 0x04
1811         }
1812     }
1813 
1814     [TypeConverter(typeof(ActivityWithResultConverter))]
1815     [ValueSerializer(typeof(ActivityWithResultValueSerializer))]
1816     public abstract class Activity<TResult> : ActivityWithResult
1817     {
1818         // alternatives are extended through DynamicActivity<TResult>, CodeActivity<TResult>, and NativeActivity<TResult>
Activity()1819         protected Activity()
1820             : base()
1821         {
1822         }
1823 
1824         [DefaultValue(null)]
1825         public new OutArgument<TResult> Result
1826         {
1827             get;
1828             set;
1829         }
1830 
1831         internal override Type InternalResultType
1832         {
1833             get
1834             {
1835                 return typeof(TResult);
1836             }
1837         }
1838 
1839         internal override OutArgument ResultCore
1840         {
1841             get
1842             {
1843                 return this.Result;
1844             }
1845             set
1846             {
1847                 this.Result = value as OutArgument<TResult>;
1848 
1849                 if (this.Result == null && value != null)
1850                 {
1851                     throw FxTrace.Exception.Argument("value", SR.ResultArgumentMustBeSpecificType(typeof(TResult)));
1852                 }
1853             }
1854         }
1855 
operator Activity<TResult>(TResult constValue)1856         public static implicit operator Activity<TResult>(TResult constValue)
1857         {
1858             return FromValue(constValue);
1859         }
1860 
operator Activity<TResult>(Variable variable)1861         public static implicit operator Activity<TResult>(Variable variable)
1862         {
1863             return FromVariable(variable);
1864         }
1865 
operator Activity<TResult>(Variable<TResult> variable)1866         public static implicit operator Activity<TResult>(Variable<TResult> variable)
1867         {
1868             return FromVariable(variable);
1869         }
1870 
FromValue(TResult constValue)1871         public static Activity<TResult> FromValue(TResult constValue)
1872         {
1873             return new Literal<TResult> { Value = constValue };
1874         }
1875 
FromVariable(Variable variable)1876         public static Activity<TResult> FromVariable(Variable variable)
1877         {
1878             if (variable == null)
1879             {
1880                 throw FxTrace.Exception.ArgumentNull("variable");
1881             }
1882 
1883             if (TypeHelper.AreTypesCompatible(variable.Type, typeof(TResult)))
1884             {
1885                 return new VariableValue<TResult> { Variable = variable };
1886             }
1887             else
1888             {
1889                 Type locationGenericType;
1890                 if (ActivityUtilities.IsLocationGenericType(typeof(TResult), out locationGenericType))
1891                 {
1892                     if (locationGenericType == variable.Type)
1893                     {
1894                         return (Activity<TResult>)ActivityUtilities.CreateVariableReference(variable);
1895                     }
1896                 }
1897             }
1898 
1899             throw FxTrace.Exception.Argument("variable", SR.ConvertVariableToValueExpressionFailed(variable.GetType().FullName, typeof(Activity<TResult>).FullName));
1900         }
1901 
1902         [SuppressMessage(FxCop.Category.Design, FxCop.Rule.ConsiderPassingBaseTypesAsParameters,
1903             Justification = "Generic needed for type inference")]
FromVariable(Variable<TResult> variable)1904         public static Activity<TResult> FromVariable(Variable<TResult> variable)
1905         {
1906             if (variable == null)
1907             {
1908                 throw FxTrace.Exception.ArgumentNull("variable");
1909             }
1910 
1911             return new VariableValue<TResult>(variable);
1912         }
1913 
IsResultArgument(RuntimeArgument argument)1914         internal override bool IsResultArgument(RuntimeArgument argument)
1915         {
1916             return object.ReferenceEquals(argument, this.ResultRuntimeArgument);
1917         }
1918 
OnInternalCacheMetadata(bool createEmptyBindings)1919         internal sealed override void OnInternalCacheMetadata(bool createEmptyBindings)
1920         {
1921             OnInternalCacheMetadataExceptResult(createEmptyBindings);
1922 
1923             bool foundResult = false;
1924 
1925             // This could be null at this point
1926             IList<RuntimeArgument> runtimeArguments = this.RuntimeArguments;
1927 
1928             int runtimeArgumentCount = 0;
1929 
1930             if (runtimeArguments != null)
1931             {
1932                 runtimeArgumentCount = runtimeArguments.Count;
1933 
1934                 for (int i = 0; i < runtimeArgumentCount; i++)
1935                 {
1936                     RuntimeArgument argument = runtimeArguments[i];
1937 
1938                     if (argument.Name == "Result")
1939                     {
1940                         foundResult = true;
1941 
1942                         if (argument.Type != typeof(TResult) || argument.Direction != ArgumentDirection.Out)
1943                         {
1944                             // The user supplied "Result" is incorrect so we
1945                             // log a violation.
1946                             AddTempValidationError(new ValidationError(SR.ResultArgumentHasRequiredTypeAndDirection(typeof(TResult), argument.Direction, argument.Type)));
1947                         }
1948                         else if (!IsBoundArgumentCorrect(argument, createEmptyBindings))
1949                         {
1950                             // The user supplied "Result" is not bound to the correct
1951                             // argument object.
1952                             AddTempValidationError(new ValidationError(SR.ResultArgumentMustBeBoundToResultProperty));
1953                         }
1954                         else
1955                         {
1956                             // The user supplied "Result" is correct so we
1957                             // cache it.
1958                             this.ResultRuntimeArgument = argument;
1959                         }
1960 
1961                         break;
1962                     }
1963                 }
1964             }
1965 
1966             if (!foundResult)
1967             {
1968                 this.ResultRuntimeArgument = new RuntimeArgument("Result", typeof(TResult), ArgumentDirection.Out);
1969 
1970                 if (this.Result == null)
1971                 {
1972                     if (createEmptyBindings)
1973                     {
1974                         this.Result = new OutArgument<TResult>();
1975                         Argument.Bind(this.Result, this.ResultRuntimeArgument);
1976                     }
1977                     else
1978                     {
1979                         OutArgument<TResult> tempArgument = new OutArgument<TResult>();
1980                         Argument.Bind(tempArgument, this.ResultRuntimeArgument);
1981                     }
1982                 }
1983                 else
1984                 {
1985                     Argument.Bind(this.Result, this.ResultRuntimeArgument);
1986                 }
1987 
1988 
1989                 AddArgument(this.ResultRuntimeArgument, createEmptyBindings);
1990             }
1991         }
1992 
IsBoundArgumentCorrect(RuntimeArgument argument, bool createEmptyBindings)1993         bool IsBoundArgumentCorrect(RuntimeArgument argument, bool createEmptyBindings)
1994         {
1995             if (createEmptyBindings)
1996             {
1997                 // We must match if we've gone through
1998                 // RuntimeArgument.SetupBinding with
1999                 // createEmptyBindings == true.
2000                 return object.ReferenceEquals(argument.BoundArgument, this.Result);
2001             }
2002             else
2003             {
2004                 // Otherwise, if the Result is null then
2005                 // SetupBinding has created a default
2006                 // BoundArgument which is fine.  If it
2007                 // is non-null then it had better match.
2008                 return this.Result == null || object.ReferenceEquals(argument.BoundArgument, this.Result);
2009             }
2010         }
2011 
OnInternalCacheMetadataExceptResult(bool createEmptyBindings)2012         internal virtual void OnInternalCacheMetadataExceptResult(bool createEmptyBindings)
2013         {
2014             // default to Activity's behavior
2015             base.OnInternalCacheMetadata(createEmptyBindings);
2016         }
2017 
InternalExecuteInResolutionContextUntyped(CodeActivityContext resolutionContext)2018         internal override object InternalExecuteInResolutionContextUntyped(CodeActivityContext resolutionContext)
2019         {
2020             return InternalExecuteInResolutionContext(resolutionContext);
2021         }
2022 
InternalExecuteInResolutionContext(CodeActivityContext resolutionContext)2023         internal virtual TResult InternalExecuteInResolutionContext(CodeActivityContext resolutionContext)
2024         {
2025             throw Fx.AssertAndThrow("This should only be called on CodeActivity<T>");
2026         }
2027     }
2028 }
2029 
2030 
2031