File: WebServiceResponse.cs
Project: ndp\cdf\src\WF\Activities\System.Workflow.Activities.csproj (System.Workflow.Activities)
using System;
using System.Reflection;
using System.Drawing;
using System.Drawing.Design;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Runtime.Remoting.Messaging;
using System.Diagnostics;
using System.Workflow.Activities.Common;
 
namespace System.Workflow.Activities
{
    [SRDescription(SR.WebServiceResponseActivityDescription)]
    [SRCategory(SR.Standard)]
    [ToolboxBitmap(typeof(WebServiceOutputActivity), "Resources.WebServiceOut.png")]
    [Designer(typeof(WebServiceResponseDesigner), typeof(IDesigner))]
    [ActivityValidator(typeof(WebServiceResponseValidator))]
    [DefaultEvent("SendingOutput")]
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class WebServiceOutputActivity : Activity, IPropertyValueProvider, IDynamicPropertyTypeProvider
    {
        //metadata properties
        public static readonly DependencyProperty InputActivityNameProperty = DependencyProperty.Register("InputActivityName", typeof(string), typeof(WebServiceOutputActivity), new PropertyMetadata("", DependencyPropertyOptions.Metadata));
 
        //instance properties
        public static readonly DependencyProperty ParameterBindingsProperty = DependencyProperty.Register("ParameterBindings", typeof(WorkflowParameterBindingCollection), typeof(WebServiceOutputActivity), new PropertyMetadata(DependencyPropertyOptions.Metadata | DependencyPropertyOptions.ReadOnly, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content) }));
 
        //event
        public static readonly DependencyProperty SendingOutputEvent = DependencyProperty.Register("SendingOutput", typeof(EventHandler), typeof(WebServiceOutputActivity));
 
        #region Constructors
 
        public WebServiceOutputActivity()
        {
            //
            base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this));
        }
 
        public WebServiceOutputActivity(string name)
            : base(name)
        {
            //
            base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this));
        }
 
        #endregion
 
        [SRCategory(SR.Activity)]
        [SRDescription(SR.ReceiveActivityNameDescription)]
        [TypeConverter(typeof(PropertyValueProviderTypeConverter))]
        [RefreshProperties(RefreshProperties.All)]
        [MergablePropertyAttribute(false)]
        [DefaultValue("")]
        public string InputActivityName
        {
            get
            {
                return base.GetValue(InputActivityNameProperty) as string;
            }
 
            set
            {
                base.SetValue(InputActivityNameProperty, value);
            }
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Browsable(false)]
        public WorkflowParameterBindingCollection ParameterBindings
        {
            get
            {
                return base.GetValue(ParameterBindingsProperty) as WorkflowParameterBindingCollection;
            }
        }
 
        [SRDescription(SR.OnBeforeResponseDescr)]
        [SRCategory(SR.Handlers)]
        [MergableProperty(false)]
        public event EventHandler SendingOutput
        {
            add
            {
                base.AddHandler(SendingOutputEvent, value);
            }
            remove
            {
                base.RemoveHandler(SendingOutputEvent, value);
            }
        }
 
 
        ICollection IPropertyValueProvider.GetPropertyValues(ITypeDescriptorContext context)
        {
            StringCollection names = new StringCollection();
            if (context.PropertyDescriptor.Name == "InputActivityName")
            {
                foreach (Activity activity in WebServiceActivityHelpers.GetPreceedingActivities(this))
                {
                    if (activity is WebServiceInputActivity)
                    {
                        names.Add(activity.QualifiedName);
                    }
                }
            }
            return names;
        }
        protected override void Initialize(IServiceProvider provider)
        {
            if (this.Parent == null)
                throw new InvalidOperationException(SR.GetString(SR.Error_MustHaveParent));
 
            base.Initialize(provider);
        }
 
        #region Execute
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            if (executionContext == null)
                throw new ArgumentNullException("executionContext");
 
            WorkflowQueuingService queueService = executionContext.GetService<WorkflowQueuingService>();
 
            // fire event
            this.RaiseEvent(WebServiceOutputActivity.SendingOutputEvent, this, EventArgs.Empty);
 
            WebServiceInputActivity webservicereceive = this.GetActivityByName(this.InputActivityName) as WebServiceInputActivity;
            if (webservicereceive == null)
            {
                Activity parent = this.Parent;
                while (parent != null)
                {
                    //typically if defined inside a custom activity
                    string qualifiedName = parent.QualifiedName + "." + this.InputActivityName;
                    webservicereceive = this.GetActivityByName(qualifiedName) as WebServiceInputActivity;
                    if (webservicereceive != null)
                        break;
                    parent = this.Parent;
                }
            }
            if (webservicereceive == null)
                throw new InvalidOperationException(SR.GetString(SR.Error_CannotResolveWebServiceInput, this.QualifiedName, this.InputActivityName));
 
            IComparable queueId = new EventQueueName(webservicereceive.InterfaceType, webservicereceive.MethodName, webservicereceive.QualifiedName);
 
            MethodInfo mInfo = webservicereceive.InterfaceType.GetMethod(webservicereceive.MethodName);
            if (!queueService.Exists(queueId))
            {
                // determine if no response is required,
                // compiler did not catch it, do the runtime check and return
                if (mInfo.ReturnType == typeof(void))
                {
                    return ActivityExecutionStatus.Closed;
                }
 
                bool isresponseRequired = false;
                foreach (ParameterInfo formalParameter in mInfo.GetParameters())
                {
                    if (formalParameter.ParameterType.IsByRef || (formalParameter.IsIn && formalParameter.IsOut))
                    {
                        isresponseRequired = true;
                    }
                }
 
                if (isresponseRequired)
                {
                    return ActivityExecutionStatus.Closed;
                }
            }
 
            if (!queueService.Exists(queueId))
                throw new InvalidOperationException(SR.GetString(SR.Error_WebServiceInputNotProcessed, webservicereceive.QualifiedName));
 
            IMethodResponseMessage responseMessage = null;
            WorkflowQueue queue = queueService.GetWorkflowQueue(queueId);
 
            if (queue.Count != 0)
                responseMessage = queue.Dequeue() as IMethodResponseMessage;
 
            IMethodMessage message = responseMessage as IMethodMessage;
 
            WorkflowParameterBindingCollection parameterBindings = this.ParameterBindings;
            ArrayList outArgs = new ArrayList();
            // populate result
            if (this.ParameterBindings.Contains("(ReturnValue)"))
            {
                WorkflowParameterBinding retBind = this.ParameterBindings["(ReturnValue)"];
                if (retBind != null)
                {
                    outArgs.Add(retBind.Value);
                }
            }
 
            foreach (ParameterInfo formalParameter in mInfo.GetParameters())
            {
                // update out and byref values
                if (formalParameter.ParameterType.IsByRef || (formalParameter.IsIn && formalParameter.IsOut))
                {
                    WorkflowParameterBinding binding = parameterBindings[formalParameter.Name];
                    outArgs.Add(binding.Value);
                }
            }
 
            // reset the waiting thread
            responseMessage.SendResponse(outArgs);
 
            return ActivityExecutionStatus.Closed;
        }
        #endregion
 
 
 
        #region IDynamicPropertyTypeProvider
 
        Type IDynamicPropertyTypeProvider.GetPropertyType(IServiceProvider serviceProvider, string propertyName)
        {
            if (propertyName == null)
                throw new ArgumentNullException("propertyName");
 
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            this.GetParameterPropertyDescriptors(parameters);
            if (parameters.ContainsKey(propertyName))
            {
                ParameterInfoBasedPropertyDescriptor descriptor = parameters[propertyName] as ParameterInfoBasedPropertyDescriptor;
                if (descriptor != null)
                    return descriptor.ParameterType;
            }
 
            return null;
        }
 
        AccessTypes IDynamicPropertyTypeProvider.GetAccessType(IServiceProvider serviceProvider, string propertyName)
        {
            if (propertyName == null)
                throw new ArgumentNullException("propertyName");
 
            return AccessTypes.Read;
        }
 
        internal void GetParameterPropertyDescriptors(IDictionary properties)
        {
            if (((IComponent)this).Site == null)
                return;
 
            ITypeProvider typeProvider = (ITypeProvider)((IComponent)this).Site.GetService(typeof(ITypeProvider));
            if (typeProvider == null)
                throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
 
            if (this.InputActivityName != null && !String.IsNullOrEmpty(this.InputActivityName.Trim()))
            {
                WebServiceInputActivity webServiceReceive = Helpers.ParseActivity(Helpers.GetRootActivity(this), this.InputActivityName) as WebServiceInputActivity;
                if (webServiceReceive != null)
                {
                    Type type = null;
                    if (webServiceReceive.InterfaceType != null)
                        type = typeProvider.GetType(webServiceReceive.InterfaceType.AssemblyQualifiedName);
 
                    if (type != null)
                    {
 
                        MethodInfo method = Helpers.GetInterfaceMethod(type, webServiceReceive.MethodName);
                        if (method != null && WebServiceActivityHelpers.ValidateParameterTypes(method).Count == 0)
                        {
                            List<ParameterInfo> inputParameters, outParameters;
                            WebServiceActivityHelpers.GetParameterInfo(method, out inputParameters, out outParameters);
 
                            foreach (ParameterInfo paramInfo in outParameters)
                            {
                                PropertyDescriptor prop = null;
                                if (paramInfo.Position == -1)
                                    prop = new ParameterInfoBasedPropertyDescriptor(typeof(WebServiceOutputActivity), paramInfo, false, DesignOnlyAttribute.Yes);
                                else
                                    prop = new ParameterInfoBasedPropertyDescriptor(typeof(WebServiceOutputActivity), paramInfo, true, DesignOnlyAttribute.Yes);
 
                                if (prop != null)
                                    properties[prop.Name] = prop;
                            }
                        }
                    }
                }
            }
        }
        #endregion
 
    }
 
    internal sealed class WebServiceResponseValidator : ActivityValidator
    {
        public override ValidationErrorCollection Validate(ValidationManager manager, object obj)
        {
            ValidationErrorCollection validationErrors = base.Validate(manager, obj);
 
            WebServiceOutputActivity webServiceResponse = obj as WebServiceOutputActivity;
            if (webServiceResponse == null)
                throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(WebServiceOutputActivity).FullName), "obj");
 
            if (Helpers.IsActivityLocked(webServiceResponse))
            {
                return validationErrors;
            }
 
            WebServiceInputActivity webServiceReceive = null;
 
            if (String.IsNullOrEmpty(webServiceResponse.InputActivityName))
                validationErrors.Add(ValidationError.GetNotSetValidationError("InputActivityName"));
            else
            {
                ITypeProvider typeProvider = (ITypeProvider)manager.GetService(typeof(ITypeProvider));
                if (typeProvider == null)
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
 
                bool foundMatchingReceive = false;
                foreach (Activity activity in WebServiceActivityHelpers.GetPreceedingActivities(webServiceResponse))
                {
                    if ((activity is WebServiceOutputActivity && String.Compare(((WebServiceOutputActivity)activity).InputActivityName, webServiceResponse.InputActivityName, StringComparison.Ordinal) == 0) ||
                        (activity is WebServiceFaultActivity && String.Compare(((WebServiceFaultActivity)activity).InputActivityName, webServiceResponse.InputActivityName, StringComparison.Ordinal) == 0))
                    {
                        if (activity is WebServiceOutputActivity)
                            validationErrors.Add(new ValidationError(SR.GetString(SR.Error_DuplicateWebServiceResponseFound, activity.QualifiedName, webServiceResponse.InputActivityName), ErrorNumbers.Error_DuplicateWebServiceResponseFound));
                        else
                            validationErrors.Add(new ValidationError(SR.GetString(SR.Error_DuplicateWebServiceFaultFound, activity.QualifiedName, webServiceResponse.InputActivityName), ErrorNumbers.Error_DuplicateWebServiceFaultFound));
                        return validationErrors;
                    }
                }
 
                foreach (Activity activity in WebServiceActivityHelpers.GetPreceedingActivities(webServiceResponse))
                {
                    if (String.Compare(activity.QualifiedName, webServiceResponse.InputActivityName, StringComparison.Ordinal) == 0)
                    {
                        if (activity is WebServiceInputActivity)
                        {
                            webServiceReceive = activity as WebServiceInputActivity;
                            foundMatchingReceive = true;
                        }
                        else
                        {
                            foundMatchingReceive = false;
                            validationErrors.Add(new ValidationError(SR.GetString(SR.Error_WebServiceReceiveNotValid, webServiceResponse.InputActivityName), ErrorNumbers.Error_WebServiceReceiveNotValid));
                            return validationErrors;
                        }
                        break;
                    }
                }
 
                if (!foundMatchingReceive)
                {
                    validationErrors.Add(new ValidationError(SR.GetString(SR.Error_WebServiceReceiveNotFound, webServiceResponse.InputActivityName), ErrorNumbers.Error_WebServiceReceiveNotFound));
                    return validationErrors;
                }
                else
                {
                    Type interfaceType = null;
                    if (webServiceReceive.InterfaceType != null)
                        interfaceType = typeProvider.GetType(webServiceReceive.InterfaceType.AssemblyQualifiedName);
 
                    if (interfaceType == null)
                    {
                        validationErrors.Add(new ValidationError(SR.GetString(SR.Error_WebServiceReceiveNotConfigured, webServiceReceive.Name), ErrorNumbers.Error_WebServiceReceiveNotConfigured));
                    }
                    else
                    {
                        // Validate method
                        if (String.IsNullOrEmpty(webServiceReceive.MethodName))
                            validationErrors.Add(new ValidationError(SR.GetString(SR.Error_WebServiceReceiveNotConfigured, webServiceReceive.Name), ErrorNumbers.Error_WebServiceReceiveNotConfigured));
                        else
                        {
                            MethodInfo methodInfo = Helpers.GetInterfaceMethod(interfaceType, webServiceReceive.MethodName);
 
                            if (methodInfo == null)
                            {
                                validationErrors.Add(new ValidationError(SR.GetString(SR.Error_WebServiceReceiveNotConfigured, webServiceReceive.Name), ErrorNumbers.Error_WebServiceReceiveNotConfigured));
                            }
                            else
                            {
                                ValidationErrorCollection parameterTypeErrors = WebServiceActivityHelpers.ValidateParameterTypes(methodInfo);
                                if (parameterTypeErrors.Count > 0)
                                {
                                    foreach (ValidationError parameterTypeError in parameterTypeErrors)
                                    {
                                        parameterTypeError.PropertyName = "InputActivityName";
                                    }
                                    validationErrors.AddRange(parameterTypeErrors);
                                }
                                else
                                {
                                    List<ParameterInfo> inputParameters, outParameters;
                                    WebServiceActivityHelpers.GetParameterInfo(methodInfo, out inputParameters, out outParameters);
 
                                    if (outParameters.Count == 0)
                                    {
                                        validationErrors.Add(new ValidationError(SR.GetString(SR.Error_WebServiceResponseNotNeeded), ErrorNumbers.Error_WebServiceResponseNotNeeded));
                                    }
                                    else
                                    {
                                        // Check to see if all output parameters have a valid bindings.
                                        foreach (ParameterInfo paramInfo in outParameters)
                                        {
                                            string paramName = paramInfo.Name;
                                            Type paramType = paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType;
 
                                            if (paramInfo.Position == -1)
                                                paramName = "(ReturnValue)";
 
                                            object paramValue = null;
                                            if (webServiceResponse.ParameterBindings.Contains(paramName))
                                            {
                                                if (webServiceResponse.ParameterBindings[paramName].IsBindingSet(WorkflowParameterBinding.ValueProperty))
                                                    paramValue = webServiceResponse.ParameterBindings[paramName].GetBinding(WorkflowParameterBinding.ValueProperty);
                                                else
                                                    paramValue = webServiceResponse.ParameterBindings[paramName].GetValue(WorkflowParameterBinding.ValueProperty);
                                            }
 
                                            if (!paramType.IsPublic || !paramType.IsSerializable)
                                            {
                                                ValidationError validationError = new ValidationError(SR.GetString(SR.Error_TypeNotPublicSerializable, paramName, paramType.FullName), ErrorNumbers.Error_TypeNotPublicSerializable);
                                                validationError.PropertyName = (String.Compare(paramName, "(ReturnValue)", StringComparison.Ordinal) == 0) ? paramName : ParameterInfoBasedPropertyDescriptor.GetParameterPropertyName(webServiceReceive.GetType(), paramName);
                                                validationErrors.Add(validationError);
                                            }
                                            else if (!webServiceResponse.ParameterBindings.Contains(paramName) || paramValue == null)
                                            {
                                                ValidationError validationError = ValidationError.GetNotSetValidationError(paramName);
                                                validationError.PropertyName = (String.Compare(paramName, "(ReturnValue)", StringComparison.Ordinal) == 0) ? paramName : ParameterInfoBasedPropertyDescriptor.GetParameterPropertyName(webServiceReceive.GetType(), paramName);
                                                validationErrors.Add(validationError);
                                            }
                                            else
                                            {
                                                AccessTypes access = AccessTypes.Read;
                                                if (paramInfo.IsOut || paramInfo.IsRetval || paramInfo.Position == -1)
                                                    access = AccessTypes.Write;
 
                                                ValidationErrorCollection variableErrors = ValidationHelpers.ValidateProperty(manager, webServiceResponse, paramValue,
                                                                                                new PropertyValidationContext(webServiceResponse.ParameterBindings[paramName], null, paramName), new BindValidationContext(paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType, access));
                                                foreach (ValidationError variableError in variableErrors)
                                                {
                                                    if (String.Compare(paramName, "(ReturnValue)", StringComparison.Ordinal) != 0)
                                                        variableError.PropertyName = ParameterInfoBasedPropertyDescriptor.GetParameterPropertyName(webServiceReceive.GetType(), paramName);
                                                }
                                                validationErrors.AddRange(variableErrors);
                                            }
                                        }
 
                                        if (webServiceResponse.ParameterBindings.Count > outParameters.Count)
                                            validationErrors.Add(new ValidationError(SR.GetString(SR.Warning_AdditionalBindingsFound), ErrorNumbers.Warning_AdditionalBindingsFound, true));
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return validationErrors;
        }
    }
 
    internal static class WebServiceActivityHelpers
    {
        private static IEnumerable GetContainedActivities(CompositeActivity activity)
        {
            if (!activity.Enabled)
                yield break;
 
            foreach (Activity containedActivity in activity.Activities)
            {
                if (containedActivity is CompositeActivity && !Helpers.IsCustomActivity((CompositeActivity)containedActivity))
                {
                    foreach (Activity nestedActivity in WebServiceActivityHelpers.GetContainedActivities((CompositeActivity)containedActivity))
                    {
                        if (nestedActivity.Enabled)
                            yield return nestedActivity;
                    }
                }
                else
                {
                    if (containedActivity.Enabled)
                        yield return containedActivity;
                }
            }
            yield break;
        }
 
        internal static IEnumerable GetPreceedingActivities(Activity startActivity)
        {
            return GetPreceedingActivities(startActivity, false);
        }
 
        internal static IEnumerable GetPreceedingActivities(Activity startActivity, bool crossOverLoop)
        {
            Activity currentActivity = null;
            Stack<Activity> activityStack = new Stack<Activity>();
            activityStack.Push(startActivity);
 
            while ((currentActivity = activityStack.Pop()) != null)
            {
                if (currentActivity is CompositeActivity && Helpers.IsCustomActivity((CompositeActivity)currentActivity))
                    break;
 
                if (currentActivity.Parent != null)
                {
                    foreach (Activity siblingActivity in currentActivity.Parent.Activities)
                    {
                        // 
                        if (siblingActivity == currentActivity && ((currentActivity.Parent is ParallelActivity && !Helpers.IsFrameworkActivity(currentActivity)) || (currentActivity.Parent is StateActivity && !Helpers.IsFrameworkActivity(currentActivity))))
                            continue;
 
                        // 
                        if (currentActivity.Parent is IfElseActivity && !Helpers.IsFrameworkActivity(currentActivity))
                            continue;
 
                        //For Listen Case.
                        if (currentActivity.Parent is ListenActivity && !Helpers.IsFrameworkActivity(currentActivity))
                            continue;
 
                        // State Machine logic:
                        // If startActivity was in the InitialState, then
                        // there are no preceeding activities. 
                        // Otherwise, we just return the parent state as
                        // the preceeding activity. 
                        StateActivity currentState = currentActivity.Parent as StateActivity;
                        if (currentState != null)
                        {
                            StateActivity enclosingState = StateMachineHelpers.FindEnclosingState(startActivity);
                            //If we are at Initial State there is no preceeding above us.
                            if (StateMachineHelpers.IsInitialState(enclosingState))
                                yield break;
                            else
                                yield return currentState;
                        }
 
                        if (siblingActivity == currentActivity)
                            break;
 
                        if (siblingActivity.Enabled)
                        {
                            if (siblingActivity is CompositeActivity && !Helpers.IsCustomActivity((CompositeActivity)siblingActivity) && (crossOverLoop || !IsLoopActivity(siblingActivity)))
                            {
                                foreach (Activity containedActivity in WebServiceActivityHelpers.GetContainedActivities((CompositeActivity)siblingActivity))
                                    yield return containedActivity;
                            }
                            else
                            {
                                yield return siblingActivity;
                            }
                        }
                    }
                }
 
                if (!crossOverLoop && IsLoopActivity(currentActivity.Parent))
                    break;
                else
                    activityStack.Push(currentActivity.Parent);
 
            }
            yield break;
        }
 
        internal static bool IsLoopActivity(Activity activity)
        {
            //
            if (activity is WhileActivity || activity is ReplicatorActivity || activity is ConditionedActivityGroup)
                return true;
 
            return false;
        }
 
        internal static bool IsInsideLoop(Activity webServiceActivity, Activity searchBoundary)
        {
            IEnumerable<String> searchBoundaryPath = GetActivityPath(searchBoundary);
            IEnumerable<String> currentActivityPath = GetActivityPath(webServiceActivity);
 
            String leastCommonParent = FindLeastCommonParent(searchBoundaryPath, currentActivityPath);
 
            Activity currentActivity = webServiceActivity;
 
            while (currentActivity.Parent != null && currentActivity.Parent.QualifiedName != leastCommonParent)
            {
                if (IsLoopActivity(currentActivity))
                    return true;
 
                currentActivity = currentActivity.Parent;
            }
 
            return false;
        }
 
        static IEnumerable<String> GetActivityPath(Activity activity)
        {
            if (activity != null)
            {
                foreach (String path in GetActivityPath(activity.Parent))
                    yield return path;
 
                yield return activity.QualifiedName;
            }
        }
 
        static String FindLeastCommonParent(IEnumerable<String> source, IEnumerable<String> dest)
        {
            IEnumerator srcEnum = source.GetEnumerator();
            IEnumerator destEnum = dest.GetEnumerator();
 
            String leastCommonParent = null;
 
            while (srcEnum.MoveNext() && destEnum.MoveNext())
            {
                if (srcEnum.Current.Equals(destEnum.Current))
                    leastCommonParent = (String)srcEnum.Current;
                else
                    return leastCommonParent;
            }
 
            return leastCommonParent;
        }
 
        internal static IEnumerable GetSucceedingActivities(Activity startActivity)
        {
            Activity currentActivity = null;
            Stack<Activity> activityStack = new Stack<Activity>();
            activityStack.Push(startActivity);
 
            while ((currentActivity = activityStack.Pop()) != null)
            {
                if (currentActivity is CompositeActivity && Helpers.IsCustomActivity((CompositeActivity)currentActivity))
                    break;
 
                if (currentActivity.Parent != null)
                {
                    bool pastCurrentActivity = false;
 
                    foreach (Activity siblingActivity in currentActivity.Parent.Activities)
                    {
                        if (siblingActivity == currentActivity)
                        {
                            pastCurrentActivity = true;
                            continue;
                        }
 
                        if (!pastCurrentActivity)
                            continue;
 
                        if (siblingActivity.Enabled)
                        {
                            if (siblingActivity is CompositeActivity && !Helpers.IsCustomActivity((CompositeActivity)siblingActivity))
                            {
                                foreach (Activity containedActivity in WebServiceActivityHelpers.GetContainedActivities((CompositeActivity)siblingActivity))
                                    yield return containedActivity;
                            }
                            else
                            {
                                yield return siblingActivity;
                            }
                        }
                    }
                }
                activityStack.Push(currentActivity.Parent);
            }
            yield break;
        }
 
        internal static void GetParameterInfo(MethodInfo methodInfo, out List<ParameterInfo> inParameters, out List<ParameterInfo> outParameters)
        {
            inParameters = new List<ParameterInfo>(); outParameters = new List<ParameterInfo>();
            foreach (ParameterInfo paramInfo in methodInfo.GetParameters())
            {
                if (paramInfo.IsOut || paramInfo.IsRetval || paramInfo.ParameterType.IsByRef)
                    outParameters.Add(paramInfo);
 
                if (!paramInfo.IsOut && !paramInfo.IsRetval)
                    inParameters.Add(paramInfo);
            }
 
            if (methodInfo.ReturnType != typeof(void))
                outParameters.Add(methodInfo.ReturnParameter);
 
            return;
        }
 
        internal static ValidationErrorCollection ValidateParameterTypes(MethodInfo methodInfo)
        {
            ValidationErrorCollection validationErrors = new ValidationErrorCollection();
            if (methodInfo == null)
                return validationErrors;
            foreach (ParameterInfo paramInfo in methodInfo.GetParameters())
            {
                if (paramInfo.ParameterType == null)
                {
                    validationErrors.Add(new ValidationError(SR.GetString(SR.Error_ParameterTypeNotFound, methodInfo.Name, paramInfo.Name), ErrorNumbers.Error_ParameterTypeNotFound));
                }
            }
 
            if (methodInfo.ReturnType != typeof(void) && methodInfo.ReturnParameter.ParameterType == null)
            {
                validationErrors.Add(new ValidationError(SR.GetString(SR.Error_ReturnTypeNotFound, methodInfo.Name), ErrorNumbers.Error_ReturnTypeNotFound));
            }
 
            return validationErrors;
        }
    }
}