ActivityUtilities.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities / System / Activities / ActivityUtilities.cs / 1305376 / ActivityUtilities.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.Activities 
{
    using System; 
    using System.Activities.Expressions; 
    using System.Activities.Runtime;
    using System.Activities.Validation; 
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel; 
    using System.Globalization;
    using System.Runtime; 
    using System.Text; 

    static class ActivityUtilities 
    {
        static Pop popActivity = new Pop();
        static Type activityType = typeof(Activity);
        static Type activityGenericType = typeof(Activity<>); 
        static Type activityDelegateType = typeof(ActivityDelegate);
        static Type constraintType = typeof(Constraint); 
        static Type variableType = typeof(Variable); 
        static Type variableGenericType = typeof(Variable<>);
        static Type delegateInArgumentType = typeof(DelegateInArgument); 
        static Type delegateOutArgumentType = typeof(DelegateOutArgument);
        static Type delegateInArgumentGenericType = typeof(DelegateInArgument<>);
        static Type delegateOutArgumentGenericType = typeof(DelegateOutArgument<>);
        static Type inArgumentType = typeof(InArgument); 
        static Type inArgumentGenericType = typeof(InArgument<>);
        static Type inOutArgumentType = typeof(InOutArgument); 
        static Type inOutArgumentGenericType = typeof(InOutArgument<>); 
        static Type outArgumentType = typeof(OutArgument);
        static Type outArgumentGenericType = typeof(OutArgument<>); 
        static Type argumentType = typeof(Argument);
        static Type argumentReferenceGenericType = typeof(ArgumentReference<>);
        static Type argumentValueGenericType = typeof(ArgumentValue<>);
        static Type runtimeArgumentType = typeof(RuntimeArgument); 
        static Type locationGenericType = typeof(Location<>);
        static Type variableReferenceGenericType = typeof(VariableReference<>); 
        static Type variableValueGenericType = typeof(VariableValue<>); 
        static Type delegateArgumentValueGenericType = typeof(DelegateArgumentValue<>);
        static Type handleType = typeof(Handle); 
        static Type iDictionaryGenericType = typeof(IDictionary<,>);
        static Type locationReferenceValueType = typeof(LocationReferenceValue<>);
        static IList collectionInterfaces;
        static Type inArgumentOfObjectType = typeof(InArgument); 
        static Type outArgumentOfObjectType = typeof(OutArgument);
        static Type inOutArgumentOfObjectType = typeof(InOutArgument); 
        static PropertyChangedEventArgs propertyChangedEventArgs; 

        // Can't delay create this one because we use object.ReferenceEquals on it in WorkflowInstance 
        static ReadOnlyDictionary emptyParameters = new ReadOnlyDictionary(new Dictionary(0));

        public static ReadOnlyDictionary EmptyParameters
        { 
            get
            { 
                return emptyParameters; 
            }
        } 

        internal static PropertyChangedEventArgs ValuePropertyChangedEventArgs
        {
            get 
            {
                if (propertyChangedEventArgs == null) 
                { 
                    propertyChangedEventArgs = new PropertyChangedEventArgs("Value");
                } 
                return propertyChangedEventArgs;
            }
        }
 
        static IList CollectionInterfaces
        { 
            get 
            {
                if (collectionInterfaces == null) 
                {
                    collectionInterfaces = new List(2)
                        {
                            typeof(IList<>), 
                            typeof(ICollection<>)
                        }; 
                } 
                return collectionInterfaces;
            } 
        }

        public static bool IsInScope(ActivityInstance potentialChild, ActivityInstance scope)
        { 
            if (scope == null)
            { 
                // No scope means we're in scope 
                return true;
            } 

            ActivityInstance walker = potentialChild;

            while (walker != null && walker != scope) 
            {
                walker = walker.Parent; 
            } 

            return walker != null; 
        }

        public static bool IsHandle(Type type)
        { 
            return handleType.IsAssignableFrom(type);
        } 
 
        public static bool IsCompletedState(ActivityInstanceState state)
        { 
            return state != ActivityInstanceState.Executing;
        }

        public static bool TryGetArgumentDirectionAndType(Type propertyType, out ArgumentDirection direction, out Type argumentType) 
        {
            direction = ArgumentDirection.In; // default to In 
            argumentType = TypeHelper.ObjectType;  // default to object 

            if (propertyType.IsGenericType) 
            {
                argumentType = propertyType.GetGenericArguments()[0];

                Type genericType = propertyType.GetGenericTypeDefinition(); 

                if (genericType == inArgumentGenericType) 
                { 
                    return true;
                } 

                if (genericType == outArgumentGenericType)
                {
                    direction = ArgumentDirection.Out; 
                    return true;
                } 
 
                if (genericType == inOutArgumentGenericType)
                { 
                    direction = ArgumentDirection.InOut;
                    return true;
                }
            } 
            else
            { 
                if (propertyType == inArgumentType) 
                {
                    return true; 
                }

                if (propertyType == outArgumentType)
                { 
                    direction = ArgumentDirection.Out;
                    return true; 
                } 

                if (propertyType == inOutArgumentType) 
                {
                    direction = ArgumentDirection.InOut;
                    return true;
                } 
            }
 
            return false; 
        }
 
        public static bool IsArgumentType(Type propertyType)
        {
            return TypeHelper.AreTypesCompatible(propertyType, argumentType);
        } 

        public static bool IsRuntimeArgumentType(Type propertyType) 
        { 
            return TypeHelper.AreTypesCompatible(propertyType, runtimeArgumentType);
        } 

        public static bool IsArgumentDictionaryType(Type type, out Type innerType)
        {
            if (type.IsGenericType) 
            {
                bool implementsIDictionary = false; 
                Type dictionaryInterfaceType = null; 

                if (type.GetGenericTypeDefinition() == iDictionaryGenericType) 
                {
                    implementsIDictionary = true;
                    dictionaryInterfaceType = type;
                } 
                else
                { 
                    foreach (Type interfaceType in type.GetInterfaces()) 
                    {
                        if (interfaceType.IsGenericType && 
                            interfaceType.GetGenericTypeDefinition() == iDictionaryGenericType)
                        {
                            implementsIDictionary = true;
                            dictionaryInterfaceType = interfaceType; 
                            break;
                        } 
                    } 
                }
 
                if (implementsIDictionary == true)
                {
                    Type[] genericArguments = dictionaryInterfaceType.GetGenericArguments();
                    if (genericArguments[0] == TypeHelper.StringType && 
                        IsArgumentType(genericArguments[1]))
                    { 
                        innerType = genericArguments[1]; 
                        return true;
                    } 
                }
            }

            innerType = null; 
            return false;
        } 
 
        public static bool IsKnownCollectionType(Type type, out Type innerType)
        { 
            if (type.IsGenericType)
            {
                if (type.IsInterface)
                { 
                    Type localInterface = type.GetGenericTypeDefinition();
                    foreach (Type knownInterface in CollectionInterfaces) 
                    { 
                        if (localInterface == knownInterface)
                        { 
                            Type[] genericArguments = type.GetGenericArguments();
                            if (genericArguments.Length == 1)
                            {
                                innerType = genericArguments[0]; 
                                return true;
                            } 
                        } 
                    }
                } 
                else
                {
                    // Ask the type whether or not it implements any known collections.
                    Type[] interfaceTypes = type.GetInterfaces(); 
                    foreach (Type interfaceType in interfaceTypes)
                    { 
                        if (interfaceType.IsGenericType) 
                        {
                            Type localInterface = interfaceType.GetGenericTypeDefinition(); 

                            foreach (Type knownInterface in CollectionInterfaces)
                            {
                                if (localInterface == knownInterface) 
                                {
                                    Type[] genericArguments = interfaceType.GetGenericArguments(); 
                                    if (genericArguments.Length == 1) 
                                    {
                                        innerType = genericArguments[0]; 
                                        return true;
                                    }
                                }
                            } 
                        }
                    } 
                } 
            }
 
            innerType = null;
            return false;
        }
 
        public static bool IsActivityDelegateType(Type propertyType)
        { 
            return TypeHelper.AreTypesCompatible(propertyType, activityDelegateType); 
        }
 
        public static bool IsActivityType(Type propertyType)
        {
            return IsActivityType(propertyType, true);
        } 

        public static bool IsActivityType(Type propertyType, bool includeConstraints) 
        { 
            if (!TypeHelper.AreTypesCompatible(propertyType, activityType))
            { 
                return false;
            }

            // sometimes (for reflection analysis of Activity properties) we don't want constraints to count 
            return includeConstraints || !TypeHelper.AreTypesCompatible(propertyType, constraintType);
        } 
 
        public static bool TryGetDelegateArgumentDirectionAndType(Type propertyType, out ArgumentDirection direction, out Type argumentType)
        { 
            direction = ArgumentDirection.In; // default to In
            argumentType = TypeHelper.ObjectType;  // default to object

            if (propertyType.IsGenericType) 
            {
                argumentType = propertyType.GetGenericArguments()[0]; 
 
                Type genericType = propertyType.GetGenericTypeDefinition();
 
                if (genericType == delegateInArgumentGenericType)
                {
                    return true;
                } 

                if (genericType == delegateOutArgumentGenericType) 
                { 
                    direction = ArgumentDirection.Out;
                    return true; 
                }
            }
            else
            { 
                if (propertyType == delegateInArgumentType)
                { 
                    return true; 
                }
 
                if (propertyType == delegateOutArgumentType)
                {
                    direction = ArgumentDirection.Out;
                    return true; 
                }
            } 
 
            return false;
        } 

        public static bool IsVariableType(Type propertyType, out Type innerType)
        {
            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == variableGenericType) 
            {
                innerType = propertyType.GetGenericArguments()[0]; 
                return true; 
            }
 
            innerType = null;
            return TypeHelper.AreTypesCompatible(propertyType, variableType);
        }
 
        public static bool IsVariableType(Type propertyType)
        { 
            if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == variableGenericType) 
            {
                return true; 
            }

            return TypeHelper.AreTypesCompatible(propertyType, variableType);
        } 

        public static bool IsLocationGenericType(Type type, out Type genericArgumentType) 
        { 
            if (type.IsGenericType && type.GetGenericTypeDefinition() == locationGenericType)
            { 
                genericArgumentType = type.GetGenericArguments()[0];
                return true;
            }
 
            genericArgumentType = null;
            return false; 
        } 

        public static object CreateVariableReference(Variable variable) 
        {
            Type genericVariableReferenceType = variableReferenceGenericType.MakeGenericType(variable.Type);
            object variableReference = Activator.CreateInstance(genericVariableReferenceType);
            genericVariableReferenceType.GetProperty("Variable").SetValue(variableReference, variable, null); 
            return variableReference;
        } 
 
        public static ActivityWithResult CreateLocationReferenceValue(LocationReference locationReference)
        { 
            Type finalType = locationReferenceValueType.MakeGenericType(locationReference.Type);

            ActivityWithResult activityWithResult = (ActivityWithResult)Activator.CreateInstance(finalType, locationReference);
 
            return activityWithResult;
        } 
 
        public static Argument CreateArgument(Type type, ArgumentDirection direction)
        { 
            Type argumentType = ArgumentTypeDefinitionsCache.GetArgumentType(type, direction);

            Argument argument = (Argument)Activator.CreateInstance(argumentType);
 
            return argument;
        } 
 
        public static Argument CreateArgumentOfObject(ArgumentDirection direction)
        { 
            Argument argument = null;

            if (direction == ArgumentDirection.In)
            { 
                argument = (Argument)Activator.CreateInstance(inArgumentOfObjectType);
            } 
            else if (direction == ArgumentDirection.Out) 
            {
                argument = (Argument)Activator.CreateInstance(outArgumentOfObjectType); 
            }
            else
            {
                argument = (Argument)Activator.CreateInstance(inOutArgumentOfObjectType); 
            }
 
            return argument; 
        }
 
        public static Type CreateLocation(Type locationType)
        {
            return locationGenericType.MakeGenericType(locationType);
        } 

        public static Type CreateActivityWithResult(Type resultType) 
        { 
            return activityGenericType.MakeGenericType(resultType);
        } 

        public static Argument CreateReferenceArgument(Type argumentType, ArgumentDirection direction, string referencedArgumentName)
        {
            Argument argument = Argument.Create(argumentType, direction); 

            object argumentReference = null; 
 
            if (direction == ArgumentDirection.In)
            { 
                // If it is an In then we need an ArgumentValue
                argumentReference = Activator.CreateInstance(argumentValueGenericType.MakeGenericType(argumentType), referencedArgumentName);
            }
            else 
            {
                // If it is InOut or Out we need an ArgumentReference 
                argumentReference = Activator.CreateInstance(argumentReferenceGenericType.MakeGenericType(argumentType), referencedArgumentName); 
            }
 
            argument.Expression = (ActivityWithResult)argumentReference;
            return argument;
        }
 
        public static Variable CreateVariable(string name, Type type, VariableModifiers modifiers)
        { 
            Type variableType = variableGenericType.MakeGenericType(type); 
            Variable variable = (Variable)Activator.CreateInstance(variableType);
            variable.Name = name; 
            variable.Modifiers = modifiers;

            return variable;
        } 

        // The argumentConsumer is the activity that is attempting to reference the argument 
        // with argumentName.  That means that argumentConsumer must be in the Implementation 
        // of an activity that defines an argument with argumentName.
        public static RuntimeArgument FindArgument(string argumentName, Activity argumentConsumer) 
        {
            if (argumentConsumer.MemberOf != null && argumentConsumer.MemberOf.Owner != null)
            {
                Activity targetActivity = argumentConsumer.MemberOf.Owner; 

                for (int i = 0; i < targetActivity.RuntimeArguments.Count; i++) 
                { 
                    RuntimeArgument argument = targetActivity.RuntimeArguments[i];
 
                    if (argument.Name == argumentName)
                    {
                        return argument;
                    } 
                }
            } 
 
            return null;
        } 

        public static string GetDisplayName(object source)
        {
            Fx.Assert(source != null, "caller must verify"); 
            return GetDisplayName(source.GetType());
        } 
 
        static string GetDisplayName(Type sourceType)
        { 
            if (sourceType.IsGenericType)
            {
                // start with the type name
                string displayName = sourceType.Name; 
                int tickIndex = displayName.IndexOf('`');
 
                // remove the tick+number of parameters "generics format". Note that the 
                // tick won't exist for nested implicitly generic classes, such as Foo`1+Bar
                if (tickIndex > 0) 
                {
                    displayName = displayName.Substring(0, tickIndex);
                }
 
                // and provide a more readable version based on the closure type names
                Type[] genericArguments = sourceType.GetGenericArguments(); 
                StringBuilder stringBuilder = new StringBuilder(displayName); 
                stringBuilder.Append("<");
                for (int i = 0; i < genericArguments.Length - 1; i++) 
                {
                    stringBuilder.AppendFormat("{0},", GetDisplayName(genericArguments[i]));
                }
                stringBuilder.AppendFormat("{0}>", GetDisplayName(genericArguments[genericArguments.Length - 1])); 
                return stringBuilder.ToString();
            } 
            else 
            {
                Fx.Assert(!sourceType.IsGenericTypeDefinition, "we have an actual object, so we should never have a generic type definition"); 
                return sourceType.Name;
            }
        }
 
        // Returns true if there are any children
        static void ProcessChildren(Activity parent, IList children, ActivityCollectionType collectionType, bool addChildren, ref ChildActivity nextActivity, ref Stack activitiesRemaining, ref IList validationErrors) 
        { 
            for (int i = 0; i < children.Count; i++)
            { 
                Activity childActivity = children[i];
                if (childActivity.InitializeRelationship(parent, collectionType, ref validationErrors))
                {
                    if (addChildren) 
                    {
                        SetupForProcessing(childActivity, collectionType != ActivityCollectionType.Imports, ref nextActivity, ref activitiesRemaining); 
                    } 
                }
            } 
        }

        // Note that we do not need an "isPublicCollection" parameter since all arguments are public
        // Returns true if there are any non-null expressions 
        static void ProcessArguments(Activity parent, IList arguments, bool addChildren, ref ActivityLocationReferenceEnvironment environment, ref int nextEnvironmentId, ref ChildActivity nextActivity, ref Stack activitiesRemaining, ref IList validationErrors)
        { 
            if (arguments.Count > 0) 
            {
                if (environment == null) 
                {
                    environment = new ActivityLocationReferenceEnvironment(parent.GetParentEnvironment());
                }
 
                for (int i = 0; i < arguments.Count; i++)
                { 
                    RuntimeArgument argument = arguments[i]; 
                    if (argument.InitializeRelationship(parent, ref validationErrors))
                    { 
                        argument.Id = nextEnvironmentId;
                        nextEnvironmentId++;

                        // This must be called after InitializeRelationship since it makes 
                        // use of RuntimeArgument.Owner;
                        environment.Declare(argument, argument.Owner, ref validationErrors); 
 
                        if (addChildren)
                        { 
                            SetupForProcessing(argument, ref nextActivity, ref activitiesRemaining);
                        }
                    }
                } 
            }
        } 
 
        // Returns true if there are any non-null defaults
        static void ProcessVariables(Activity parent, IList variables, ActivityCollectionType collectionType, bool addChildren, ref ActivityLocationReferenceEnvironment environment, ref int nextEnvironmentId, ref ChildActivity nextActivity, ref Stack activitiesRemaining, ref IList validationErrors) 
        {
            if (variables.Count > 0)
            {
                if (environment == null) 
                {
                    environment = new ActivityLocationReferenceEnvironment(parent.GetParentEnvironment()); 
                } 

                for (int i = 0; i < variables.Count; i++) 
                {
                    Variable variable = variables[i];
                    if (variable.InitializeRelationship(parent, collectionType == ActivityCollectionType.Public, ref validationErrors))
                    { 
                        variable.Id = nextEnvironmentId;
                        nextEnvironmentId++; 
 
                        // This must be called after InitializeRelationship since it makes
                        // use of Variable.Owner; 
                        environment.Declare(variable, variable.Owner, ref validationErrors);

                        if (addChildren)
                        { 
                            SetupForProcessing(variable, ref nextActivity, ref activitiesRemaining);
                        } 
                    } 
                }
            } 
        }

        // Returns true if there are any non-null handlers
        static void ProcessDelegates(Activity parent, IList delegates, ActivityCollectionType collectionType, bool addChildren, ref ChildActivity nextActivity, ref Stack activitiesRemaining, ref IList validationErrors) 
        {
            for (int i = 0; i < delegates.Count; i++) 
            { 
                ActivityDelegate activityDelegate = delegates[i];
                if (activityDelegate.InitializeRelationship(parent, collectionType, ref validationErrors)) 
                {
                    if (addChildren)
                    {
                        SetupForProcessing(activityDelegate, collectionType != ActivityCollectionType.Imports, ref nextActivity, ref activitiesRemaining); 
                    }
                } 
            } 
        }
 
        static void ProcessActivity(ChildActivity childActivity, ref ChildActivity nextActivity, ref Stack activitiesRemaining, ActivityCallStack parentChain, ref IList validationErrors, ProcessActivityTreeOptions options, ProcessActivityCallback callback)
        {
            Activity activity = childActivity.Activity;
            IList constraints = activity.RuntimeConstraints; 
            IList tempValidationErrors = null;
 
            Fx.Assert(validationErrors == null || !options.StoreTempViolations, "Incoming violations should be null if we are storing them in Activity.tempViolations."); 

            if (!activity.HasStartedCachingMetadata) 
            {
                // We need to add this activity to the IdSpace first so that we have a meaningful ID
                // for any errors that may occur.
                Fx.Assert(activity.MemberOf != null, "We always set this ahead of time - the root is set in InitializeAsRoot and all others are set in InitializeRelationship."); 
                activity.MemberOf.AddMember(activity);
 
                activity.InternalCacheMetadata(options.CreateEmptyBindings, ref tempValidationErrors); 

                ActivityValidationServices.ValidateArguments(activity, activity.Parent == null, ref tempValidationErrors); 

                ActivityLocationReferenceEnvironment newPublicEnvironment = null;
                ActivityLocationReferenceEnvironment newImplementationEnvironment = new ActivityLocationReferenceEnvironment(activity.HostEnvironment)
                { 
                    InternalRoot = activity
                }; 
 
                int nextEnvironmentId = 0;
 
                ProcessChildren(activity, activity.Children, ActivityCollectionType.Public, true, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors);
                ProcessChildren(activity, activity.ImportedChildren, ActivityCollectionType.Imports, true, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors);
                ProcessChildren(activity, activity.ImplementationChildren, ActivityCollectionType.Implementation, !options.SkipPrivateChildren, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors);
 
                ProcessArguments(activity, activity.RuntimeArguments, true, ref newImplementationEnvironment, ref nextEnvironmentId, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors);
 
                ProcessVariables(activity, activity.RuntimeVariables, ActivityCollectionType.Public, true, ref newPublicEnvironment, ref nextEnvironmentId, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors); 
                ProcessVariables(activity, activity.ImplementationVariables, ActivityCollectionType.Implementation, !options.SkipPrivateChildren, ref newImplementationEnvironment, ref nextEnvironmentId, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors);
 
                if (activity.HandlerOf != null)
                {
                    // Since we are a delegate handler we have to do some processing
                    // of the handlers parameters.  This is the one part of the tree 
                    // walk that actually reaches _up_ to process something we've
                    // already passed. 
 
                    for (int i = 0; i < activity.HandlerOf.RuntimeDelegateArguments.Count; i++)
                    { 
                        RuntimeDelegateArgument delegateArgument = activity.HandlerOf.RuntimeDelegateArguments[i];
                        DelegateArgument boundArgument = delegateArgument.BoundArgument;
                        if (boundArgument != null)
                        { 
                            // At runtime, delegate arguments end up owned by the Handler
                            // and are scoped like public variables of the handler. 
                            // 
                            // And since they don't own an expression, there's no equivalent
                            // SetupForProcessing method for DelegateArguments 
                            if (boundArgument.InitializeRelationship(activity, ref tempValidationErrors))
                            {
                                boundArgument.Id = nextEnvironmentId;
                                nextEnvironmentId++; 
                            }
                        } 
                    } 
                }
 
                // NOTE: At this point the declared environment is complete (either we're using the parent or we've got a new one)
                if (newPublicEnvironment == null)
                {
                    activity.PublicEnvironment = new ActivityLocationReferenceEnvironment(activity.GetParentEnvironment()); 
                }
                else 
                { 
                    if (newPublicEnvironment.Parent == null)
                    { 
                        newPublicEnvironment.InternalRoot = activity;
                    }

                    activity.PublicEnvironment = newPublicEnvironment; 
                }
 
                activity.ImplementationEnvironment = newImplementationEnvironment; 

                // ProcessDelegates uses activity.Environment 
                ProcessDelegates(activity, activity.Delegates, ActivityCollectionType.Public, true, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors);
                ProcessDelegates(activity, activity.ImportedDelegates, ActivityCollectionType.Imports, true, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors);
                ProcessDelegates(activity, activity.ImplementationDelegates, ActivityCollectionType.Implementation, !options.SkipPrivateChildren, ref nextActivity, ref activitiesRemaining, ref tempValidationErrors);
 
                if (callback != null)
                { 
                    callback(childActivity, parentChain); 
                }
 
                // copy validation errors in ValidationErrors list
                if (tempValidationErrors != null)
                {
                    if (validationErrors == null) 
                    {
                        validationErrors = new List(); 
                    } 
                    Activity source;
                    string prefix = ActivityValidationServices.GenerateValidationErrorPrefix(childActivity.Activity, parentChain, out source); 

                    for (int i = 0; i < tempValidationErrors.Count; i++)
                    {
                        ValidationError validationError = tempValidationErrors[i]; 

                        validationError.Source = source; 
                        validationError.Id = source.Id; 

                        if (!string.IsNullOrEmpty(prefix)) 
                        {
                            validationError.Message = prefix + validationError.Message;
                        }
 
                        validationErrors.Add(validationError);
                    } 
 
                    tempValidationErrors = null;
                } 

                if (options.StoreTempViolations)
                {
                    if (validationErrors != null) 
                    {
                        childActivity.Activity.SetTempValidationErrorCollection(validationErrors); 
                        validationErrors = null; 
                    }
                } 
            }
            else
            {
                // We're processing a reference 

 
                // Add all the children for processing even though they've already 
                // been seen.
                SetupForProcessing(activity.Children, true, ref nextActivity, ref activitiesRemaining); 
                SetupForProcessing(activity.ImportedChildren, false, ref nextActivity, ref activitiesRemaining);

                SetupForProcessing(activity.RuntimeArguments, ref nextActivity, ref activitiesRemaining);
 
                SetupForProcessing(activity.RuntimeVariables, ref nextActivity, ref activitiesRemaining);
 
                SetupForProcessing(activity.Delegates, true, ref nextActivity, ref activitiesRemaining); 
                SetupForProcessing(activity.ImportedDelegates, false, ref nextActivity, ref activitiesRemaining);
 
                if (!options.SkipPrivateChildren)
                {
                    SetupForProcessing(activity.ImplementationChildren, true, ref nextActivity, ref activitiesRemaining);
                    SetupForProcessing(activity.ImplementationDelegates, true, ref nextActivity, ref activitiesRemaining); 
                    SetupForProcessing(activity.ImplementationVariables, ref nextActivity, ref activitiesRemaining);
                } 
 
                if (callback != null && !options.OnlyCallCallbackForDeclarations)
                { 
                    callback(childActivity, parentChain);
                }

                if (childActivity.Activity.HasTempViolations && !options.StoreTempViolations) 
                {
                    childActivity.Activity.TransferTempValidationErrors(ref validationErrors); 
                } 
            }
 
            // We only run constraints if the activity could possibly
            // execute and we aren't explicitly skipping them.
            if (!options.SkipConstraints && parentChain.WillExecute && childActivity.CanBeExecuted && constraints.Count > 0)
            { 
                ActivityValidationServices.RunConstraints(childActivity, parentChain, constraints, options, false, ref validationErrors);
            } 
        } 

        // We explicitly call this CacheRootMetadata since it treats the provided 
        // activity as the root of the tree.
        public static void CacheRootMetadata(Activity activity, LocationReferenceEnvironment hostEnvironment, ProcessActivityTreeOptions options, ProcessActivityCallback callback, ref IList validationErrors)
        {
            if (!ShouldShortcut(activity, options)) 
            {
                lock (activity.ThisLock) 
                { 
                    if (!ShouldShortcut(activity, options))
                    { 
                        if (activity.HasBeenAssociatedWithAnInstance)
                        {
                            throw FxTrace.Exception.AsError(new InvalidOperationException(SR.RootActivityAlreadyAssociatedWithInstance(activity.DisplayName)));
                        } 

                        activity.InitializeAsRoot(hostEnvironment); 
 
                        ProcessActivityTreeCore(new ChildActivity(activity, true), null, options, callback, ref validationErrors);
 
                        // Regardless of where the violations came from we only want to
                        // set ourselves RuntimeReady if there are no errors and are
                        // fully cached.
                        if (!ActivityValidationServices.HasErrors(validationErrors) && options.IsRuntimeReadyOptions) 
                        {
                            // We don't really support progressive caching at runtime so we only set ourselves 
                            // as runtime ready if we cached the whole workflow and created empty bindings. 
                            // In order to support progressive caching we need to deal with the following
                            // issues: 
                            //   * We need a mechanism for supporting activities which supply extensions
                            //   * We need to understand when we haven't created empty bindings so that
                            //     we can progressively create them
                            //   * We need a mechanism for making sure that we've validated parent related 
                            //     constraints at all possible callsites
                            activity.SetRuntimeReady(); 
                        } 
                    }
                } 
            }
        }

        // This API is only valid from ProcessActivityCallbacks.  It will cache the rest of the subtree rooted at the 
        // provided activity allowing inspection of child metadata before the normal caching pass hits it.
        public static void FinishCachingSubtree(ChildActivity subtreeRoot, ActivityCallStack parentChain, ProcessActivityTreeOptions options) 
        { 
            IList discardedValidationErrors = null;
            ProcessActivityTreeCore(subtreeRoot, parentChain, ProcessActivityTreeOptions.GetFinishCachingSubtreeOptions(options), new ProcessActivityCallback(NoOpCallback), ref discardedValidationErrors); 
        }

        public static void FinishCachingSubtree(ChildActivity subtreeRoot, ActivityCallStack parentChain, ProcessActivityTreeOptions options, ProcessActivityCallback callback)
        { 
            IList discardedValidationErrors = null;
            ProcessActivityTreeCore(subtreeRoot, parentChain, ProcessActivityTreeOptions.GetFinishCachingSubtreeOptions(options), callback, ref discardedValidationErrors); 
        } 

        static void NoOpCallback(ChildActivity element, ActivityCallStack parentChain) 
        {
        }

        static bool ShouldShortcut(Activity activity, ProcessActivityTreeOptions options) 
        {
            if (options.SkipIfCached && options.IsRuntimeReadyOptions) 
            { 
                return activity.IsRuntimeReady;
            } 

            return false;
        }
 
        static void ProcessActivityTreeCore(ChildActivity currentActivity, ActivityCallStack parentChain, ProcessActivityTreeOptions options, ProcessActivityCallback callback, ref IList validationErrors)
        { 
            Fx.Assert(options != null, "We need you to explicitly specify options."); 
            Fx.Assert(currentActivity.Activity.MemberOf != null, "We must have an activity with MemberOf setup or we need to skipIdGeneration.");
 
            ChildActivity nextActivity = ChildActivity.Empty;
            Stack activitiesRemaining = null;

            if (parentChain == null) 
            {
                parentChain = new ActivityCallStack(); 
            } 

            if (options.OnlyVisitSingleLevel) 
            {
                ProcessActivity(currentActivity, ref nextActivity, ref activitiesRemaining, parentChain, ref validationErrors, options, callback);
            }
            else 
            {
                while (!currentActivity.Equals(ChildActivity.Empty)) 
                { 
                    if (object.ReferenceEquals(currentActivity.Activity, popActivity))
                    { 
                        ChildActivity completedParent = parentChain.Pop();
                        completedParent.Activity.SetCached();
                    }
                    else 
                    {
                        SetupForProcessing(popActivity, true, ref nextActivity, ref activitiesRemaining); 
                        ProcessActivity(currentActivity, ref nextActivity, ref activitiesRemaining, parentChain, ref validationErrors, options, callback); 
                        parentChain.Push(currentActivity);
                    } 

                    // nextActivity is the top of the stack
                    //    stackTop => nextActivity => currentActivity
                    currentActivity = nextActivity; 

                    if (activitiesRemaining != null && activitiesRemaining.Count > 0) 
                    { 
                        nextActivity = activitiesRemaining.Pop();
                    } 
                    else
                    {
                        nextActivity = ChildActivity.Empty;
                    } 
                }
            } 
        } 

        static void SetupForProcessing(IList children, bool canBeExecuted, ref ChildActivity nextActivity, ref Stack activitiesRemaining) 
        {
            for (int i = 0; i < children.Count; i++)
            {
                SetupForProcessing(children[i], canBeExecuted, ref nextActivity, ref activitiesRemaining); 
            }
        } 
 
        static void SetupForProcessing(IList delegates, bool canBeExecuted, ref ChildActivity nextActivity, ref Stack activitiesRemaining)
        { 
            for (int i = 0; i < delegates.Count; i++)
            {
                SetupForProcessing(delegates[i], canBeExecuted, ref nextActivity, ref activitiesRemaining);
            } 
        }
 
        static void SetupForProcessing(IList variables, ref ChildActivity nextActivity, ref Stack activitiesRemaining) 
        {
            for (int i = 0; i < variables.Count; i++) 
            {
                SetupForProcessing(variables[i], ref nextActivity, ref activitiesRemaining);
            }
        } 

        static void SetupForProcessing(IList arguments, ref ChildActivity nextActivity, ref Stack activitiesRemaining) 
        { 
            for (int i = 0; i < arguments.Count; i++)
            { 
                SetupForProcessing(arguments[i], ref nextActivity, ref activitiesRemaining);
            }
        }
 
        static void SetupForProcessing(ActivityDelegate activityDelegate, bool canBeExecuted, ref ChildActivity nextActivity, ref Stack activitiesRemaining)
        { 
            if (activityDelegate.Handler != null) 
            {
                SetupForProcessing(activityDelegate.Handler, canBeExecuted, ref nextActivity, ref activitiesRemaining); 
            }
        }

        static void SetupForProcessing(Variable variable, ref ChildActivity nextActivity, ref Stack activitiesRemaining) 
        {
            if (variable.Default != null) 
            { 
                SetupForProcessing(variable.Default, true, ref nextActivity, ref activitiesRemaining);
            } 
        }

        static void SetupForProcessing(RuntimeArgument argument, ref ChildActivity nextActivity, ref Stack activitiesRemaining)
        { 
            if (argument.BoundArgument != null && !argument.BoundArgument.IsEmpty)
            { 
                SetupForProcessing(argument.BoundArgument.Expression, true, ref nextActivity, ref activitiesRemaining); 
            }
        } 

        // nextActivity is always the top of the stack
        static void SetupForProcessing(Activity activity, bool canBeExecuted, ref ChildActivity nextActivity, ref Stack activitiesRemaining)
        { 
            if (!nextActivity.Equals(ChildActivity.Empty))
            { 
                if (activitiesRemaining == null) 
                {
                    activitiesRemaining = new Stack(); 
                }

                activitiesRemaining.Push(nextActivity);
            } 

            nextActivity = new ChildActivity(activity, canBeExecuted); 
        } 

        public static void ProcessActivityInstanceTree(ActivityInstance rootInstance, ActivityExecutor executor, Func callback) 
        {
            Queue> instancesRemaining = null;

            TreeProcessingList currentInstancesList = new TreeProcessingList(); 
            currentInstancesList.Add(rootInstance);
 
            TreeProcessingList nextInstanceList = null; 
            if (rootInstance.HasChildren)
            { 
                nextInstanceList = new TreeProcessingList();
            }

            while ((instancesRemaining != null && instancesRemaining.Count > 0) 
                || currentInstancesList.Count != 0)
            { 
                if (currentInstancesList.Count == 0) 
                {
                    Fx.Assert(instancesRemaining != null && instancesRemaining.Count > 0, "This must be the clause that caused us to enter"); 
                    currentInstancesList.Set(instancesRemaining.Dequeue());
                }

                for (int i = 0; i < currentInstancesList.Count; i++) 
                {
                    ActivityInstance instance = currentInstancesList[i]; 
 
                    if (callback(instance, executor) && instance.HasChildren)
                    { 
                        Fx.Assert(nextInstanceList != null, "We should have created this list if we are going to get here.");
                        instance.AppendChildren(nextInstanceList, ref instancesRemaining);
                    }
                } 

                if (nextInstanceList != null && nextInstanceList.Count > 0) 
                { 
                    nextInstanceList.TransferTo(currentInstancesList);
                } 
                else
                {
                    // We'll just reuse this object on the next pass (Set will be called)
                    currentInstancesList.Reset(); 
                }
            } 
        } 

        public delegate void ProcessActivityCallback(ChildActivity childActivity, ActivityCallStack parentChain); 

        public static FaultBookmark CreateFaultBookmark(FaultCallback onFaulted, ActivityInstance owningInstance)
        {
            if (onFaulted != null) 
            {
                return new FaultBookmark(new FaultCallbackWrapper(onFaulted, owningInstance)); 
            } 
            return null;
        } 

        public static CompletionBookmark CreateCompletionBookmark(CompletionCallback onCompleted, ActivityInstance owningInstance)
        {
            if (onCompleted != null) 
            {
                return new CompletionBookmark(new ActivityCompletionCallbackWrapper(onCompleted, owningInstance)); 
            } 
            return null;
        } 

        public static CompletionBookmark CreateCompletionBookmark(DelegateCompletionCallback onCompleted, ActivityInstance owningInstance)
        {
            if (onCompleted != null) 
            {
                return new CompletionBookmark(new DelegateCompletionCallbackWrapper(onCompleted, owningInstance)); 
            } 
            return null;
        } 

        public static CompletionBookmark CreateCompletionBookmark(CompletionCallback onCompleted, ActivityInstance owningInstance)
        {
            if (onCompleted != null) 
            {
                return new CompletionBookmark(new FuncCompletionCallbackWrapper(onCompleted, owningInstance)); 
            } 

            return null; 
        }

        public static string GetTraceString(Bookmark bookmark)
        { 
            if (bookmark.IsNamed)
            { 
                return "'" + bookmark.Name + "'"; 
            }
            else 
            {
                return string.Format(CultureInfo.InvariantCulture, "", bookmark.Id);
            }
        } 

        public static string GetTraceString(BookmarkScope bookmarkScope) 
        { 
            if (bookmarkScope == null)
            { 
                return "";
            }
            else if (bookmarkScope.IsInitialized)
            { 
                return "'" + bookmarkScope.Id.ToString() + "'";
            } 
            else 
            {
                return string.Format(CultureInfo.InvariantCulture, "", bookmarkScope.TemporaryId); 
            }
        }

        public static void RemoveNulls(IList list) 
        {
            if (list != null) 
            { 
                for (int i = list.Count - 1; i >= 0; i--)
                { 
                    if (list[i] == null)
                    {
                        list.RemoveAt(i);
                    } 
                }
            } 
        } 

        public static void Add(ref Collection collection, T data) 
        {
            if (data != null)
            {
                if (collection == null) 
                {
                    collection = new Collection(); 
                } 
                collection.Add(data);
            } 
        }

        public static void Add(ref IList list, T data)
        { 
            if (data != null)
            { 
                if (list == null) 
                {
                    list = new List(); 
                }
                list.Add(data);
            }
        } 

        public class TreeProcessingList 
        { 
            ActivityInstance singleItem;
            IList multipleItems; 
            bool addRequiresNewList;

            public TreeProcessingList()
            { 
            }
 
            public int Count 
            {
                get 
                {
                    if (this.singleItem != null)
                    {
                        return 1; 
                    }
 
                    if (this.multipleItems != null) 
                    {
                        return this.multipleItems.Count; 
                    }

                    return 0;
                } 
            }
 
            public ActivityInstance this[int index] 
            {
                get 
                {
                    if (this.singleItem != null)
                    {
                        Fx.Assert(index == 0, "We expect users of TreeProcessingList never to be out of range."); 
                        return this.singleItem;
                    } 
                    else 
                    {
                        Fx.Assert(this.multipleItems != null, "Users shouldn't call this if we have no items."); 
                        Fx.Assert(this.multipleItems.Count > index, "Users should never be out of range.");

                        return this.multipleItems[index];
                    } 
                }
            } 
 
            public void Set(IList listToSet)
            { 
                Fx.Assert(singleItem == null && (this.multipleItems == null || this.multipleItems.Count == 0), "We should not have any items if calling set.");

                this.multipleItems = listToSet;
                this.addRequiresNewList = true; 
            }
 
            public void Add(ActivityInstance item) 
            {
                if (this.multipleItems != null) 
                {
                    if (this.addRequiresNewList)
                    {
                        this.multipleItems = new List(this.multipleItems); 
                        this.addRequiresNewList = false;
                    } 
 
                    this.multipleItems.Add(item);
                } 
                else if (this.singleItem != null)
                {
                    this.multipleItems = new List(2);
                    this.multipleItems.Add(this.singleItem); 
                    this.multipleItems.Add(item);
                    this.singleItem = null; 
                } 
                else
                { 
                    this.singleItem = item;
                }
            }
 
            // Because of how we use this we don't need a Clear().
            // Basically we gain nothing by clearing the multipleItems 
            // list and hanging onto it. 
            public void Reset()
            { 
                this.addRequiresNewList = false;
                this.multipleItems = null;
                this.singleItem = null;
            } 

            public void TransferTo(TreeProcessingList otherList) 
            { 
                otherList.singleItem = this.singleItem;
                otherList.multipleItems = this.multipleItems; 
                otherList.addRequiresNewList = this.addRequiresNewList;

                Reset();
            } 
        }
 
        // We don't implement anything in this class.  We just use it as 
        // a placeholder for when to pop off our parent stack.
        class Pop : Activity 
        {
            internal override void InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
            {
                throw Fx.AssertAndThrow("should never get here"); 
            }
 
            internal override void OnInternalCacheMetadata(bool createEmptyBindings) 
            {
                throw Fx.AssertAndThrow("should never get here"); 
            }
        }

        public struct ChildActivity : IEquatable 
        {
            public ChildActivity(Activity activity, bool canBeExecuted) 
                : this() 
            {
                Activity = activity; 
                CanBeExecuted = canBeExecuted;
            }

            public static ChildActivity Empty 
            {
                get 
                { 
                    return new ChildActivity();
                } 
            }

            public Activity Activity
            { 
                get;
                set; 
            } 

            public bool CanBeExecuted 
            {
                get;
                set;
            } 

            public bool Equals(ChildActivity other) 
            { 
                return object.ReferenceEquals(Activity, other.Activity) && CanBeExecuted == other.CanBeExecuted;
            } 
        }

        public class ActivityCallStack
        { 
            int nonExecutingParentCount;
            Quack callStack; 
 
            public ActivityCallStack()
            { 
                callStack = new Quack();
            }

            public bool WillExecute 
            {
                get 
                { 
                    return nonExecutingParentCount == 0;
                } 
            }

            public ChildActivity this[int index]
            { 
                get
                { 
                    return this.callStack[index]; 
                }
            } 

            public int Count
            {
                get 
                {
                    return this.callStack.Count; 
                } 
            }
 
            public void Push(ChildActivity childActivity)
            {
                if (!childActivity.CanBeExecuted)
                { 
                    this.nonExecutingParentCount++;
                } 
 
                this.callStack.PushFront(childActivity);
            } 

            public ChildActivity Pop()
            {
                ChildActivity childActivity = this.callStack.Dequeue(); 

                if (!childActivity.CanBeExecuted) 
                { 
                    this.nonExecutingParentCount--;
                } 

                return childActivity;
            }
        } 

        static class ArgumentTypeDefinitionsCache 
        { 
            static Hashtable inArgumentTypeDefinitions = new Hashtable();
            static Hashtable outArgumentTypeDefinitions = new Hashtable(); 
            static Hashtable inOutArgumentTypeDefinitions = new Hashtable();

            public static Type GetArgumentType(Type type, ArgumentDirection direction)
            { 
                Hashtable lookupTable = null;
 
                if (direction == ArgumentDirection.In) 
                {
                    lookupTable = inArgumentTypeDefinitions; 
                }
                else if (direction == ArgumentDirection.Out)
                {
                    lookupTable = outArgumentTypeDefinitions; 
                }
                else 
                { 
                    lookupTable = inOutArgumentTypeDefinitions;
                } 

                Type argumentType = lookupTable[type] as Type;
                if (argumentType == null)
                { 
                    argumentType = CreateArgumentType(type, direction);
                    lock (lookupTable) 
                    { 
                        lookupTable[type] = argumentType;
                    } 
                }

                return argumentType;
            } 

            static Type CreateArgumentType(Type type, ArgumentDirection direction) 
            { 
                Type argumentType = null;
 
                if (direction == ArgumentDirection.In)
                {
                    argumentType = ActivityUtilities.inArgumentGenericType.MakeGenericType(type);
                } 
                else if (direction == ArgumentDirection.Out)
                { 
                    argumentType = ActivityUtilities.outArgumentGenericType.MakeGenericType(type); 
                }
                else 
                {
                    argumentType = ActivityUtilities.inOutArgumentGenericType.MakeGenericType(type);
                }
 
                return argumentType;
            } 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK