EventSinkActivity.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 / WF / Activities / EventSinkActivity.cs / 1305376 / EventSinkActivity.cs

                            namespace System.Workflow.Activities 
{
    using System;
    using System.Reflection;
    using System.Collections; 
    using System.ComponentModel;
    using System.ComponentModel.Design; 
    using System.Drawing; 
    using System.Drawing.Design;
    using System.Workflow.Runtime; 
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.Runtime.Hosting;
    using System.Workflow.ComponentModel.Compiler; 
    using System.ComponentModel.Design.Serialization;
    using System.Collections.Generic; 
    using System.Collections.Specialized; 
    using System.Runtime.Serialization;
    using System.Workflow.Activities.Common; 

    [SRDescription(SR.HandleExternalEventActivityDescription)]
    [DefaultEvent("Invoked")]
    [Designer(typeof(HandleExternalEventActivityDesigner), typeof(IDesigner))] 
    [ActivityValidator(typeof(HandleExternalEventActivityValidator))]
    [SRCategory(SR.Base)] 
    public class HandleExternalEventActivity : Activity, IEventActivity, IPropertyValueProvider, IActivityEventListener, IDynamicPropertyTypeProvider 
    {
        //instance properties 
        public static readonly DependencyProperty CorrelationTokenProperty = DependencyProperty.Register("CorrelationToken", typeof(CorrelationToken), typeof(HandleExternalEventActivity),new PropertyMetadata(DependencyPropertyOptions.Metadata));
        public static readonly DependencyProperty RolesProperty = DependencyProperty.Register("Roles", typeof(WorkflowRoleCollection), typeof(HandleExternalEventActivity));
        public static readonly DependencyProperty ParameterBindingsProperty = DependencyProperty.Register("ParameterBindings", typeof(WorkflowParameterBindingCollection), typeof(HandleExternalEventActivity), new PropertyMetadata(DependencyPropertyOptions.Metadata | DependencyPropertyOptions.ReadOnly, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content) }));
        private static DependencyProperty ActivitySubscribedProperty = DependencyProperty.Register("ActivitySubscribed", typeof(bool), typeof(HandleExternalEventActivity), new PropertyMetadata(false)); 
        private static DependencyProperty QueueNameProperty = DependencyProperty.Register("QueueName", typeof(IComparable), typeof(HandleExternalEventActivity));
 
        //metadata properties 
        public static readonly DependencyProperty InterfaceTypeProperty = DependencyProperty.Register("InterfaceType", typeof(System.Type), typeof(HandleExternalEventActivity), new PropertyMetadata(null, DependencyPropertyOptions.Metadata, new Attribute[] { new ValidationOptionAttribute(ValidationOption.Required) }));
        public static readonly DependencyProperty EventNameProperty = DependencyProperty.Register("EventName", typeof(string), typeof(HandleExternalEventActivity), new PropertyMetadata("", DependencyPropertyOptions.Metadata, new Attribute[] { new ValidationOptionAttribute(ValidationOption.Required) })); 

        //event
        public static readonly DependencyProperty InvokedEvent = DependencyProperty.Register("Invoked", typeof(EventHandler), typeof(HandleExternalEventActivity));
 
        internal static readonly ArrayList ReservedParameterNames = new ArrayList(new string[] { "Name", "Enabled", "Description", "EventName", "InterfaceType", "Invoked", "Roles" });
 
        #region Constructors 

        public HandleExternalEventActivity() 
        {
            base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this));
        }
 
        public HandleExternalEventActivity(string name)
            : base(name) 
        { 
            base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this));
        } 

        #endregion

        [RefreshProperties(RefreshProperties.All)] 
        [TypeConverter(typeof(PropertyValueProviderTypeConverter))]
        [SRCategory(SR.Activity)] 
        [SRDescription(SR.ExternalEventNameDescr)] 
        [MergablePropertyAttribute(false)]
        [DefaultValue("")] 
        public virtual string EventName
        {
            get
            { 
                return base.GetValue(EventNameProperty) as string;
            } 
 
            set
            { 
                base.SetValue(EventNameProperty, value);
            }
        }
 
        [SRCategory(SR.Activity)]
        [SRDescription(SR.HelperExternalDataExchangeDesc)] 
        [RefreshProperties(RefreshProperties.All)] 
        [Editor(typeof(TypeBrowserEditor), typeof(UITypeEditor))]
        [TypeFilterProviderAttribute(typeof(ExternalDataExchangeInterfaceTypeFilterProvider))] 
        [DefaultValue(null)]
        public virtual Type InterfaceType
        {
            get 
            {
                return base.GetValue(InterfaceTypeProperty) as Type; 
            } 

            set 
            {
                base.SetValue(InterfaceTypeProperty, value);
            }
        } 

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
        [Browsable(false)] 
        public WorkflowParameterBindingCollection ParameterBindings
        { 
            get
            {
                return base.GetValue(ParameterBindingsProperty) as WorkflowParameterBindingCollection;
            } 
        }
 
        [SRCategory(SR.Activity)] 
        [SRDescription(SR.RoleDescr)]
        [Editor(typeof(BindUITypeEditor), typeof(UITypeEditor))] 
        [DefaultValue(null)]
        public WorkflowRoleCollection Roles
        {
            get 
            {
                return base.GetValue(RolesProperty) as WorkflowRoleCollection; 
            } 
            set
            { 
                base.SetValue(RolesProperty, value);
            }
        }
 
        [SRCategory(SR.Activity)]
        [RefreshProperties(RefreshProperties.All)] 
        [SRDescription(SR.CorrelationSetDescr)] 
        [MergableProperty(false)]
        [TypeConverter(typeof(CorrelationTokenTypeConverter))] 
        [DefaultValue(null)]
        public virtual CorrelationToken CorrelationToken
          {
            get 
            {
                return base.GetValue(CorrelationTokenProperty) as CorrelationToken; 
            } 
            set
            { 
                base.SetValue(CorrelationTokenProperty, value);
            }
        }
 
        [SRCategory(SR.Handlers)]
        [SRDescription(SR.OnAfterMethodInvokeDescr)] 
        [MergableProperty(false)] 
        public event EventHandler Invoked
        { 
            add
            {
                base.AddHandler(InvokedEvent, value);
            } 
            remove
            { 
                base.RemoveHandler(InvokedEvent, value); 
            }
        } 

        private bool ActivitySubscribed
        {
            get 
            {
                return (bool)base.GetValue(ActivitySubscribedProperty); 
            } 
            set
            { 
                base.SetValue(ActivitySubscribedProperty, value);
            }
        }
 
        ICollection IPropertyValueProvider.GetPropertyValues(ITypeDescriptorContext context)
        { 
            StringCollection names = new StringCollection(); 
            if (this.InterfaceType == null)
                return names; 

            if (context.PropertyDescriptor.Name == "EventName")
            {
                foreach (EventInfo eventInfo in this.InterfaceType.GetEvents(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)) 
                    names.Add(eventInfo.Name);
            } 
            return names; 
        }
 
        protected override void InitializeProperties()
        {
            ActivityHelpers.InitializeCorrelationTokenCollection(this, this.CorrelationToken);
 
            Type type = this.InterfaceType;
            if (type == null) 
                throw new InvalidOperationException(SR.GetString(SR.InterfaceTypeMissing, this.Name)); 

            string eventName = this.EventName; 
            if (eventName == null)
                throw new InvalidOperationException(SR.GetString(SR.EventNameMissing, this.Name));

            EventInfo eventInfo = type.GetEvent(eventName); 
            if (eventInfo != null)
            { 
                MethodInfo methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke"); 
                InvokeHelper.InitializeParameters(methodInfo, this.ParameterBindings);
            } 
            else
            {
                throw new InvalidOperationException(SR.GetString(SR.MethodInfoMissing, this.EventName, this.InterfaceType.Name));
            } 

            base.InitializeProperties(); 
        } 

        protected sealed override void Initialize(IServiceProvider provider) 
        {
            if (provider == null)
                throw new ArgumentNullException("provider");
 
            //When activity is dropped inside multi instance container(replicator)
            //We delay CorrelationService initialization to template initialization time. 
            if ((!this.IsDynamicActivity && !IsNestedUnderMultiInstanceContainer) || IsInitializingUnderMultiInstanceContainer) 
            {
                Type type = this.InterfaceType; 
                string eventName = this.EventName;
                IComparable queueName = null;
                if (CorrelationResolver.IsInitializingMember(type, eventName, null))
                    queueName = new EventQueueName(type, eventName); 
                this.SetValue(QueueNameProperty, queueName);
 
                CorrelationService.Initialize(provider, this, type, eventName, this.WorkflowInstanceId); 
            }
        } 

        //Only MultiInstance container we have today is Replicator
        bool IsInitializingUnderMultiInstanceContainer
        { 
            get
            { 
                CompositeActivity parent = this.Parent; 
                Activity templateChild = this;
 
                while (parent != null)
                {
                    //Need to look at attribute/interface
                    if (parent is ReplicatorActivity) 
                        break;
 
                    //If we cross execution context then return false. 
                    if (!parent.GetActivityByName(templateChild.QualifiedName).Equals(templateChild))
                        return false; 

                    templateChild = parent;
                    parent = parent.Parent;
                } 

                if(parent != null) 
                    return !parent.GetActivityByName(templateChild.QualifiedName).Equals(templateChild); 

                return false; 
            }
        }

        bool IsNestedUnderMultiInstanceContainer 
        {
            get 
            { 
                CompositeActivity parent = this.Parent;
 
                while (parent != null)
                {
                    //Need to look at attribute/interface
                    if (parent is ReplicatorActivity) 
                        return true;
 
                    parent = parent.Parent; 
                }
 
                return false;
            }
        }
 
        protected virtual void OnInvoked(EventArgs e)
        { 
        } 

        #region Execute/Cancel 

        protected sealed override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            if (executionContext == null) 
                throw new ArgumentNullException("executionContext");
 
            object[] args = null; 
            ActivityExecutionStatus status = InboundActivityHelper.ExecuteForActivity(this, executionContext, this.InterfaceType, this.EventName, out args);
            if (status == ActivityExecutionStatus.Closed) 
            {
                RaiseEvent(args);
                UnsubscribeForActivity(executionContext);
                executionContext.CloseActivity(); 
                return status;
            } 
 
            // cannot resolve queue name or message not available
            // hence subscribe for message arrival 
            if (!this.ActivitySubscribed)
            {
                this.ActivitySubscribed = CorrelationService.Subscribe(executionContext, this, this.InterfaceType, this.EventName, this, this.WorkflowInstanceId);
            } 

            return ActivityExecutionStatus.Executing; 
        } 

        protected sealed override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception) 
        {
            if (executionContext == null)
                throw new ArgumentNullException("executionContext");
 
            if (exception == null)
                throw new ArgumentNullException("exception"); 
 
            ActivityExecutionStatus newStatus = this.Cancel(executionContext);
            if (newStatus == ActivityExecutionStatus.Canceling) 
                return ActivityExecutionStatus.Faulting;

            return newStatus;
        } 

        protected sealed override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext) 
        { 
            if (executionContext == null)
                throw new ArgumentNullException("executionContext"); 

            UnsubscribeForActivity(executionContext);

            return ActivityExecutionStatus.Closed; 
        }
 
        protected override void OnClosed(IServiceProvider provider) 
        {
            base.RemoveProperty(HandleExternalEventActivity.ActivitySubscribedProperty); 
        }

        private void UnsubscribeForActivity(ActivityExecutionContext context)
        { 
            if (this.ActivitySubscribed)
            { 
                CorrelationService.Unsubscribe(context, this, this.InterfaceType, this.EventName, this); 
                this.ActivitySubscribed = false;
            } 
        }

        void IActivityEventListener.OnEvent(object sender, QueueEventArgs e)
        { 
            ActivityExecutionContext context = (ActivityExecutionContext)sender;
            HandleExternalEventActivity activity = context.Activity as HandleExternalEventActivity; 
 
            // if activity is not scheduled for execution do not dequeue the message
            if (activity.ExecutionStatus != ActivityExecutionStatus.Executing) return; 

            object[] args = null;
            ActivityExecutionStatus status = InboundActivityHelper.ExecuteForActivity(this, context, this.InterfaceType, this.EventName, out args);
            if (status == ActivityExecutionStatus.Closed) 
            {
                RaiseEvent(args); 
                UnsubscribeForActivity(context); 
                context.CloseActivity();
            } 
        }

        private void RaiseEvent(object[] args)
        { 
            if (args != null)
            { 
                ExternalDataEventArgs extArgs = args[1] as ExternalDataEventArgs; 
                OnInvoked(extArgs);
                this.RaiseGenericEvent(InvokedEvent, args[0], extArgs); 
            }
            else
            {
                OnInvoked(EventArgs.Empty); 
                this.RaiseGenericEvent(InvokedEvent, this, EventArgs.Empty);
            } 
 
        }
        #endregion 

        #region IEventActivity members
        void IEventActivity.Subscribe(ActivityExecutionContext parentContext, IActivityEventListener parentEventHandler)
        { 
            if (parentContext == null)
                throw new ArgumentNullException("parentContext"); 
            if (parentEventHandler == null) 
                throw new ArgumentNullException("parentEventHandler");
 
            CorrelationService.Subscribe(parentContext, this, InterfaceType, EventName, parentEventHandler, this.WorkflowInstanceId);
        }

        void IEventActivity.Unsubscribe(ActivityExecutionContext parentContext, IActivityEventListener parentEventHandler) 
        {
            if (parentContext == null) 
                throw new ArgumentNullException("parentContext"); 
            if (parentEventHandler == null)
                throw new ArgumentNullException("parentEventHandler"); 

            CorrelationService.Unsubscribe(parentContext, this, InterfaceType, EventName, parentEventHandler);
        }
 
        IComparable IEventActivity.QueueName
        { 
            get 
            {
                IComparable queueName = (IComparable)this.GetValue(QueueNameProperty); 
                if (queueName != null)
                    return queueName;
                else
                    return CorrelationService.ResolveQueueName(this, InterfaceType, EventName); 
            }
        } 
 
        #endregion
 
        #region IDynamicPropertyTypeProvider

        Type IDynamicPropertyTypeProvider.GetPropertyType(IServiceProvider serviceProvider, string propertyName)
        { 
            if (propertyName == null)
                throw new ArgumentNullException("propertyName"); 
 
            Dictionary parameters = new Dictionary();
            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));
 
            Type type = this.InterfaceType;
            if (type == null)
                return;
 
            if (this.GetType() != typeof(HandleExternalEventActivity))
                return; // if custom activity do not add parameter binding 
 
            EventInfo eventInfo = type.GetEvent(this.EventName);
            if (eventInfo != null) 
            {
                Type delegateType = TypeProvider.GetEventHandlerType(eventInfo);
                if (delegateType != null)
                { 
                    MethodInfo method = delegateType.GetMethod("Invoke");
                    ArrayList paramInfo = new ArrayList(); 
                    if (method != null) 
                    {
                        paramInfo.AddRange(method.GetParameters()); 
                        if (!(method.ReturnType == typeof(void)))
                            paramInfo.Add(method.ReturnParameter);
                    }
 
                    foreach (ParameterInfo param in paramInfo)
                    { 
                        PropertyDescriptor prop = new ParameterInfoBasedPropertyDescriptor(typeof(HandleExternalEventActivity), param, true, DesignOnlyAttribute.Yes); 
                        properties[prop.Name] = prop;
                    } 
                }
            }
        }
        #endregion 
    }
 
    public class HandleExternalEventActivityValidator : ActivityValidator 
    {
        public override ValidationErrorCollection Validate(ValidationManager manager, object obj) 
        {
            HandleExternalEventActivity eventSink = obj as HandleExternalEventActivity;
            if (eventSink == null)
                throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(HandleExternalEventActivity).FullName), "obj"); 

            ValidationErrorCollection validationErrors = base.Validate(manager, obj); 
            validationErrors.AddRange(CorrelationSetsValidator.Validate(manager, obj)); 
            validationErrors.AddRange(ParameterBindingValidator.Validate(manager, obj));
            return validationErrors; 
        }
    }

    internal class ExternalDataExchangeInterfaceTypeFilterProvider : ITypeFilterProvider 
    {
        private IServiceProvider serviceProvider; 
        public ExternalDataExchangeInterfaceTypeFilterProvider(IServiceProvider serviceProvider) 
        {
            this.serviceProvider = serviceProvider; 
        }

        public bool CanFilterType(Type type, bool throwOnError)
        { 
            if (type.IsInterface)
            { 
                object[] dsAttribs = type.GetCustomAttributes(typeof(ExternalDataExchangeAttribute), false); 
                if (dsAttribs.Length != 0)
                    return true; 
                else if (throwOnError)
                    throw new Exception(SR.GetString(SR.Error_InterfaceTypeNeedsExternalDataExchangeAttribute, "InterfaceType"));
            }
          /*  else 
            {
                Type[] types = type.GetNestedTypes(); 
                foreach (Type nestedType in types) 
                {
                    object[] dsAttribs = nestedType.GetCustomAttributes(typeof(ExternalDataExchangeAttribute), false); 
                    if (dsAttribs.Length != 0)
                        return true;
                }
            }*/ 

            if (throwOnError) 
                throw new Exception(SR.GetString(SR.Error_InterfaceTypeNotInterface, "InterfaceType")); 

            return false; 
        }

        public string FilterDescription
        { 
            get
            { 
                return SR.GetString(SR.ShowingExternalDataExchangeService); 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

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