File: InvokeSchedule.cs
Project: ndp\cdf\src\WF\Activities\System.Workflow.Activities.csproj (System.Workflow.Activities)
namespace System.Workflow.Activities
{
    #region Imports
 
    using System;
    using System.IO;
    using System.Xml;
    using System.Text;
    using System.Reflection;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing;
    using System.Diagnostics;
    using System.Drawing.Design;
    using System.ComponentModel.Design;
    using System.ComponentModel.Design.Serialization;
    using System.CodeDom;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design;
    using System.Collections.Generic;
    using System.Workflow.ComponentModel.Compiler;
    using System.Workflow.Runtime;
    using System.Workflow.Runtime.Hosting;
    using System.Collections.Specialized;
    using System.Workflow.Activities.Common;
 
    #endregion
 
    // Note that the designer is associated dynamically through the type description provider
    [SRDescription(SR.InvokeWorkflowActivityDescription)]
    [ToolboxItem(typeof(ActivityToolboxItem))]
    [ToolboxBitmap(typeof(InvokeWorkflowActivity), "Resources.Service.bmp")]
    [ActivityValidator(typeof(InvokeWorkflowValidator))]
    [DefaultEvent("Invoking")]
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class InvokeWorkflowActivity : Activity, ITypeFilterProvider
    {
        public static readonly DependencyProperty TargetWorkflowProperty = DependencyProperty.Register("TargetWorkflow", typeof(Type), typeof(InvokeWorkflowActivity), new PropertyMetadata(null, DependencyPropertyOptions.Metadata));
        public static readonly DependencyProperty ParameterBindingsProperty = DependencyProperty.Register("ParameterBindings", typeof(WorkflowParameterBindingCollection), typeof(InvokeWorkflowActivity), new PropertyMetadata(DependencyPropertyOptions.Metadata | DependencyPropertyOptions.ReadOnly, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content) }));
 
        public static readonly DependencyProperty InvokingEvent = DependencyProperty.Register("Invoking", typeof(EventHandler), typeof(InvokeWorkflowActivity));
 
        public static readonly DependencyProperty InstanceIdProperty = DependencyProperty.Register("InstanceId", typeof(Guid), typeof(InvokeWorkflowActivity), new PropertyMetadata(Guid.Empty));
 
        internal static readonly ArrayList ReservedParameterNames = new ArrayList(new string[] { "Name", "Enabled", "Description", "TargetWorkflow", "Invoking", "ParameterBindings" });
 
        #region Constructors
 
        public InvokeWorkflowActivity()
        {
            //
            base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this));
        }
 
        public InvokeWorkflowActivity(string name)
            : base(name)
        {
            //
            base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this));
        }
 
        #endregion
 
        [SRCategory(SR.Activity)]
        [SRDescription(SR.TargetWorkflowDescr)]
        [Editor(typeof(TypeBrowserEditor), typeof(UITypeEditor))]
        [DefaultValue(null)]
        public Type TargetWorkflow
        {
            get
            {
                return base.GetValue(TargetWorkflowProperty) as Type;
            }
            set
            {
                base.SetValue(TargetWorkflowProperty, value);
            }
        }
 
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Guid InstanceId
        {
            get
            {
                return (Guid)base.GetValue(InstanceIdProperty);
            }
        }
 
        internal void SetInstanceId(Guid value)
        {
            //
            base.SetValue(InstanceIdProperty, value);
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Browsable(false)]
        public WorkflowParameterBindingCollection ParameterBindings
        {
            get
            {
                return base.GetValue(ParameterBindingsProperty) as WorkflowParameterBindingCollection;
            }
        }
 
        [SRCategory(SR.Handlers)]
        [SRDescription(SR.InitializeCaleeDescr)]
        [MergableProperty(false)]
        public event EventHandler Invoking
        {
            add
            {
                base.AddHandler(InvokingEvent, value);
            }
            remove
            {
                base.RemoveHandler(InvokingEvent, value);
            }
        }
 
        #region ITypeFilterProvider Members
 
        bool ITypeFilterProvider.CanFilterType(Type type, bool throwOnError)
        {
            if (type == null)
                throw new ArgumentNullException("type");
 
            bool canFilterType = TypeProvider.IsAssignable(typeof(Activity), type) && type != typeof(Activity) && !type.IsAbstract;
            if (canFilterType)
            {
                //This means that the type is DesignTimeType
                IDesignerHost designerHost = ((IComponent)this).Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (designerHost != null && String.Compare(designerHost.RootComponentClassName, type.FullName, StringComparison.Ordinal) == 0)
                {
                    if (throwOnError)
                        throw new InvalidOperationException(SR.GetString(SR.Error_CantInvokeSelf));
                    else
                        canFilterType = false;
                }
            }
 
            if (throwOnError && !canFilterType)
                throw new Exception(SR.GetString(SR.Error_TypeIsNotRootActivity, "TargetWorkflow"));
 
            return canFilterType;
        }
 
        string ITypeFilterProvider.FilterDescription
        {
            get
            {
                return SR.GetString(SR.FilterDescription_InvokeWorkflow);
            }
        }
 
        #endregion
 
        #region Execute
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            if (executionContext == null)
                throw new ArgumentNullException("executionContext");
 
            // raise event
            base.RaiseEvent(InvokeWorkflowActivity.InvokingEvent, this, EventArgs.Empty);
 
            // collect the [in] parameters
            Dictionary<string, object> namedArgumentValues = new Dictionary<string, object>();
            foreach (WorkflowParameterBinding paramBinding in this.ParameterBindings)
                namedArgumentValues.Add(paramBinding.ParameterName, paramBinding.Value);
 
            IStartWorkflow workflowInvoker = executionContext.GetService(typeof(IStartWorkflow)) as IStartWorkflow;
            if (workflowInvoker == null)
                throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IStartWorkflow).FullName));
 
            Guid instanceId = workflowInvoker.StartWorkflow(this.TargetWorkflow, namedArgumentValues);
            if (instanceId == Guid.Empty)
                throw new InvalidOperationException(SR.GetString(SR.Error_FailedToStartTheWorkflow));
 
            this.SetInstanceId(instanceId);
 
            return ActivityExecutionStatus.Closed;
        }
        #endregion
 
    }
 
    #region validator
    internal sealed class InvokeWorkflowValidator : ActivityValidator
    {
        public override ValidationErrorCollection Validate(ValidationManager manager, object obj)
        {
            ValidationErrorCollection validationErrors = base.Validate(manager, obj);
 
            InvokeWorkflowActivity invokeWorkflow = obj as InvokeWorkflowActivity;
            if (invokeWorkflow == null)
                throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(InvokeWorkflowActivity).FullName), "obj");
 
            if (invokeWorkflow.TargetWorkflow == null)
            {
                ValidationError error = new ValidationError(SR.GetString(SR.Error_TypePropertyInvalid, "TargetWorkflow"), ErrorNumbers.Error_PropertyNotSet);
                error.PropertyName = "TargetWorkflow";
                validationErrors.Add(error);
            }
            else
            {
                ITypeProvider typeProvider = (ITypeProvider)manager.GetService(typeof(ITypeProvider));
                if (typeProvider == null)
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
 
                Type targetWorkflowType = invokeWorkflow.TargetWorkflow;
                if (targetWorkflowType.Assembly == null && typeProvider.LocalAssembly != null)
                {
                    Type workflowType = typeProvider.LocalAssembly.GetType(targetWorkflowType.FullName);
                    if (workflowType != null)
                        targetWorkflowType = workflowType;
                }
 
                if (!TypeProvider.IsAssignable(typeof(Activity), targetWorkflowType))
                {
                    ValidationError error = new ValidationError(SR.GetString(SR.Error_TypeIsNotRootActivity, "TargetWorkflow"), ErrorNumbers.Error_TypeIsNotRootActivity);
                    error.PropertyName = "TargetWorkflow";
                    validationErrors.Add(error);
                }
                else
                {
                    Activity rootActivity = null;
                    try
                    {
                        rootActivity = Activator.CreateInstance(targetWorkflowType) as Activity;
                    }
                    catch (Exception)
                    {
                        //
                    }
 
                    if (rootActivity == null)
                    {
                        ValidationError error = new ValidationError(SR.GetString(SR.Error_GetCalleeWorkflow, invokeWorkflow.TargetWorkflow), ErrorNumbers.Error_GetCalleeWorkflow);
                        error.PropertyName = "TargetWorkflow";
                        validationErrors.Add(error);
                    }
                    else
                    {
                        // Exec can't have activate receive.
                        Walker walker = new Walker();
                        walker.FoundActivity += delegate(Walker w, WalkerEventArgs args)
                        {
                            if ((args.CurrentActivity is WebServiceInputActivity && ((WebServiceInputActivity)args.CurrentActivity).IsActivating))
                            {
                                ValidationError validationError = new ValidationError(SR.GetString(SR.Error_ExecWithActivationReceive), ErrorNumbers.Error_ExecWithActivationReceive);
                                validationError.PropertyName = "Name";
                                validationErrors.Add(validationError);
 
                                args.Action = WalkerAction.Abort;
                            }
                        };
 
                        walker.Walk((Activity)rootActivity);
 
                        bool inAtomicScope = false;
                        Activity parentScope = invokeWorkflow.Parent;
                        while (parentScope != null)
                        {
                            if (parentScope is CompensatableTransactionScopeActivity || parentScope is TransactionScopeActivity)
                            {
                                inAtomicScope = true;
                                break;
                            }
                            parentScope = parentScope.Parent;
                        }
 
                        // Validate that if the workflow is transactional or being exec'd then it is not enclosed in an atomic scope.
                        if (inAtomicScope)
                        {
                            ValidationError validationError = new ValidationError(SR.GetString(SR.Error_ExecInAtomicScope), ErrorNumbers.Error_ExecInAtomicScope);
                            validationErrors.Add(validationError);
                        }
 
                        foreach (WorkflowParameterBinding paramBinding in invokeWorkflow.ParameterBindings)
                        {
                            PropertyInfo propertyInfo = null;
 
                            propertyInfo = targetWorkflowType.GetProperty(paramBinding.ParameterName);
                            if (propertyInfo == null)
                            {
                                ValidationError validationError = new ValidationError(SR.GetString(SR.Error_ParameterNotFound, paramBinding.ParameterName), ErrorNumbers.Error_ParameterNotFound);
                                if (InvokeWorkflowActivity.ReservedParameterNames.Contains(paramBinding.ParameterName))
                                    validationError.PropertyName = ParameterInfoBasedPropertyDescriptor.GetParameterPropertyName(invokeWorkflow.GetType(), paramBinding.ParameterName);
 
                                validationErrors.Add(validationError);
                                continue;
                            }
 
                            Type parameterType = propertyInfo.PropertyType;
                            if (paramBinding.GetBinding(WorkflowParameterBinding.ValueProperty) != null)
                            {
                                ValidationErrorCollection memberErrors = ValidationHelpers.ValidateProperty(manager, invokeWorkflow, paramBinding.GetBinding(WorkflowParameterBinding.ValueProperty), new PropertyValidationContext(paramBinding, null, paramBinding.ParameterName), new BindValidationContext(parameterType, AccessTypes.Read));
 
                                if (memberErrors.Count != 0)
                                {
                                    validationErrors.AddRange(memberErrors);
                                    continue;
                                }
                            }
                        }
                    }
                }
            }
 
            return validationErrors;
        }
    }
    #endregion
}