CustomActivityDesigner.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Common / AuthoringOM / Design / CustomActivityDesigner.cs / 1305376 / CustomActivityDesigner.cs

                            namespace System.Workflow.ComponentModel.Design 
{
    #region Using directives

    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Text; 
    using System.ComponentModel;
    using System.Drawing.Design; 
    using System.ComponentModel.Design;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Compiler;
    using System.Globalization; 
    using System.Reflection;
    using System.Reflection.Emit; 
    using System.ComponentModel.Design.Serialization; 
    using System.Windows.Forms;
    using System.Windows.Forms.Design; 
    using System.CodeDom;

    #endregion
 
    #region Class CustomActivityDesignerAdapter
 
 	internal sealed class CustomActivityDesignerAdapter : IDisposable 
    {
        private IServiceProvider								serviceProvider = null; 
		private EventHandler									ensureChildHierarchyHandler = null;

        public CustomActivityDesignerAdapter(IServiceProvider serviceProvider)
        { 
            this.serviceProvider = serviceProvider;
 
            IComponentChangeService componentChangeService = this.serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService; 
            if (componentChangeService != null)
            { 
                componentChangeService.ComponentAdding += new ComponentEventHandler(OnComponentAdding);
                componentChangeService.ComponentAdded += new ComponentEventHandler(OnComponentAdded);
            }
        } 

        void IDisposable.Dispose() 
        { 
            if (this.ensureChildHierarchyHandler != null)
            { 
                Application.Idle -= this.ensureChildHierarchyHandler;
                this.ensureChildHierarchyHandler = null;
            }
 
            IComponentChangeService componentChangeService = this.serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
            if (componentChangeService != null) 
            { 
                componentChangeService.ComponentAdding -= new ComponentEventHandler(OnComponentAdding);
                componentChangeService.ComponentAdded -= new ComponentEventHandler(OnComponentAdded); 
            }
        }

        #region Helpers 
        private void OnComponentAdding(object sender, ComponentEventArgs eventArgs)
        { 
            //We are adding root component, while doing this make sure that we provide the root designer attribute 
            IDesignerHost designerHost = (IDesignerHost)this.serviceProvider.GetService(typeof(IDesignerHost));
            if (designerHost != null) 
            {
                if (designerHost.RootComponent == null)
                {
                    Activity rootActivity = eventArgs.Component as Activity; 
                    if (rootActivity != null)
                    { 
                        //Add root designer attribute 
                        DesignerAttribute rootDesignerAttrib = GetDesignerAttribute(rootActivity, typeof(IRootDesigner));
                        if (rootDesignerAttrib.DesignerTypeName == typeof(ActivityDesigner).AssemblyQualifiedName) 
                        {
                            DesignerAttribute designerAttrib = GetDesignerAttribute(rootActivity, typeof(IDesigner));
                            if (designerAttrib != null)
                                TypeDescriptor.AddAttributes(rootActivity, new Attribute[] { new DesignerAttribute(designerAttrib.DesignerTypeName, typeof(IRootDesigner)) }); 
                        }
                    } 
                } 
            }
        } 

        private void OnComponentAdded(object sender, ComponentEventArgs eventArgs)
        {
            IDesignerHost designerHost = (IDesignerHost)this.serviceProvider.GetService(typeof(IDesignerHost)); 
            if (designerHost != null)
            { 
                if (designerHost.RootComponent == eventArgs.Component) 
                {
                    Activity rootActivity = designerHost.RootComponent as Activity; 
                    if (rootActivity != null)
                    {
                        CompositeActivity compositeActivity = rootActivity as CompositeActivity;
                        if (compositeActivity != null) 
                        {
                            if (this.ensureChildHierarchyHandler == null) 
                            { 
                                this.ensureChildHierarchyHandler = new EventHandler(OnEnsureChildHierarchy);
                                Application.Idle += this.ensureChildHierarchyHandler; 
                            }
                        }
                        rootActivity.UserData[UserDataKeys.CustomActivity] = false;
                    } 
                }
                else if (eventArgs.Component is Activity) 
                { 
                    if ((eventArgs.Component is CompositeActivity) && Helpers.IsCustomActivity(eventArgs.Component as CompositeActivity))
                        (eventArgs.Component as Activity).UserData[UserDataKeys.CustomActivity] = true; 
                    else
                        (eventArgs.Component as Activity).UserData[UserDataKeys.CustomActivity] = false;
                }
            } 
        }
 
        ///PLEASE NOTE: We have added this handler for a reason. When the user changes the base type of the Activity 
        ///we reload the designer after flushing the changes to the buffer, we do that in the IDesignerHost.TransactionClosed event
        /// The reload of the designer is then done on Idle event; but during reload we add extra components in the composite activity 
        /// which in short modifies the composite activity,but during loading process the BasicDesignerLoader ignores such modification and
        /// does not tag the buffer as modified. The problem which happens due to this is that we wont flush the changes caused by
        /// adding of additional components to the buffer there by not saving the child designers. Hence instead of adding components during reload
        /// we add them in the first idle event after reload. 
        private void OnEnsureChildHierarchy(object sender, EventArgs e)
        { 
            if (this.ensureChildHierarchyHandler != null) 
            {
                Application.Idle -= this.ensureChildHierarchyHandler; 
                this.ensureChildHierarchyHandler = null;

                IDesignerHost designerHost = (IDesignerHost)this.serviceProvider.GetService(typeof(IDesignerHost));
                if (designerHost != null) 
                    EnsureDefaultChildHierarchy(designerHost);
            } 
        } 

        private static DesignerAttribute GetDesignerAttribute(object component, Type designerBaseType) 
        {
            AttributeCollection attribs = TypeDescriptor.GetAttributes(component);
            foreach (Attribute attribute in attribs)
            { 
                DesignerAttribute designerAttribute = attribute as DesignerAttribute;
                if (designerAttribute != null && designerAttribute.DesignerBaseTypeName == designerBaseType.AssemblyQualifiedName) 
                    return designerAttribute; 
            }
 
            return null;
        }

		private static void EnsureDefaultChildHierarchy(IDesignerHost designerHost) 
		{
            //When we are adding the root activity we need to make sure that all the child activities which are required by the parent 
            //activity are looked up in the toolboxitem and added appropriately 
            //If the composite activity already has a some child activities but not all then it
            //means that user has changed the InitializeComponent and hence we do nothing 
            //This is the simple check to get the designer working in case of selecting composite
            //root activities
            CompositeActivity rootActivity = designerHost.RootComponent as CompositeActivity;
            if (rootActivity != null && rootActivity.Activities.Count == 0) 
            {
 				object[] attribs = rootActivity.GetType().GetCustomAttributes(typeof(ToolboxItemAttribute), false); 
                ToolboxItemAttribute toolboxItemAttrib = (attribs != null && attribs.GetLength(0) > 0) ? attribs[0] as ToolboxItemAttribute : null; 
                if (toolboxItemAttrib != null && toolboxItemAttrib.ToolboxItemType != null)
                { 
					ToolboxItem item = Activator.CreateInstance(toolboxItemAttrib.ToolboxItemType, new object[] { rootActivity.GetType() }) as ToolboxItem;
                    IComponent[] components = item.CreateComponents();

                    //I am assuming here that there will be always one top level component created. 
                    //If there are multiple then there is a bigger problem as we dont know how
                    //to use those 
                    CompositeActivity compositeActivity = null; 
                    foreach (IComponent component in components)
                    { 
 						if (component.GetType() == rootActivity.GetType())
                        {
                            compositeActivity = component as CompositeActivity;
                            break; 
                        }
                    } 
 
                    //Add the children
                    if (compositeActivity != null && compositeActivity.Activities.Count > 0) 
                    {
                        IIdentifierCreationService identifierCreationService = designerHost.GetService(typeof(IIdentifierCreationService)) as IIdentifierCreationService;
                        if (identifierCreationService != null)
                        { 
                            //We do not go thru the composite designer here as composite activity
                            //might have simple designer 
                            Activity[] activities = compositeActivity.Activities.ToArray(); 
                            compositeActivity.Activities.Clear();
 
                            identifierCreationService.EnsureUniqueIdentifiers(rootActivity, activities);
 							// Work around : Don't called AddRange because it doesn't send the ListChange notifications
							// to the activity collection.  Use multiple Add calls instaead
 							foreach (Activity newActivity in activities) 
								rootActivity.Activities.Add(newActivity);
 
                            foreach (Activity childActivity in activities) 
                                WorkflowDesignerLoader.AddActivityToDesigner(designerHost, childActivity);
                        } 
                    }
                }
            }
        } 
        #endregion
    } 
    #endregion 

    #region Extenders 

    #region Class CustomActivityPropertyExtender
    [ProvideProperty("BaseActivityType", typeof(Activity))]
    internal sealed class CustomActivityPropertyExtender : IExtenderProvider 
    {
        public CustomActivityPropertyExtender() 
        { 
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [SRDisplayName(SR.BaseActivityType)]
		[SRCategory(SR.ActivityDesc)]
		[SRDescription(SR.CustomActivityBaseTypeDesc)] 
 		[Editor(typeof(TypeBrowserEditor), typeof(UITypeEditor))]
		[DesignOnly(true)] 
 		[TypeFilterProvider(typeof(BaseClassTypeFilterProvider))] 
        [DefaultValue("System.Workflow.ComponentModel.Sequence")]
 		public string GetBaseActivityType(Activity activity) 
		{
            // The activity type will be the base type.  No need for more complicated logic here.
            return activity.GetType().FullName;
        } 

 		//Do not remove this function, it is being called indirectly 
        public void SetBaseActivityType(Activity activity, string baseActivityTypeName) 
        {
            CustomActivityDesignerHelper.SetBaseTypeName(baseActivityTypeName, activity.Site); 

			// Once the base type is changed, cause each of the companion class properties
			// to set their value again, updating their base types appropriatly
		} 

        bool IExtenderProvider.CanExtend(object extendee) 
        { 
            bool canExtend = false;
 
            Activity activity = extendee as Activity;
            if (activity != null && activity.Site != null && activity == Helpers.GetRootActivity(activity))
            {
                ActivityDesigner rootDesigner = ActivityDesigner.GetDesigner(activity); 
                if (rootDesigner != null && rootDesigner.ParentDesigner == null)
                    canExtend = true; 
            } 

            return canExtend; 
        }
    }
    #endregion
 
    #endregion
 
    #region Class CustomActivityDesignerHelper 
    internal static class CustomActivityDesignerHelper
 	{ 
		#region Base Type Helper Methods
        public static Type GetCustomActivityType(IServiceProvider serviceProvider)
        {
 			IDesignerHost host = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; 
 			if (host == null)
				throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName)); 
 
 			string className = host.RootComponentClassName;
            if (string.IsNullOrEmpty(className)) 
                return null;

			ITypeProvider typeProvider = serviceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider;
			if (typeProvider == null) 
				throw new Exception(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
 
            return typeProvider.GetType(className, false); 
        }
 
 		public static void SetBaseTypeName(string typeName, IServiceProvider serviceProvider)
		{
 			if (string.IsNullOrEmpty(typeName))
 				throw new ArgumentNullException("typeName"); 

            IDesignerHost host = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; 
            if (host == null) 
                throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
 
            IMemberCreationService memberCreationService = serviceProvider.GetService(typeof(IMemberCreationService)) as IMemberCreationService;
            if (memberCreationService == null)
                throw new InvalidOperationException(SR.GetString("General_MissingService", typeof(IMemberCreationService).FullName));
 
			// Validate the base type (this will throw an exception if the type name isn't valid
 			Type newBaseType = ValidateBaseType(typeName, serviceProvider); 
 
			//Warn the user of the change
			Type oldBaseType = host.RootComponent.GetType(); 
			if (oldBaseType == newBaseType)
 				return;

            // If we're switch to a base type that is not derived from CompositeActivity, make sure 
            // we dont's support events or exceptions
            if (!TypeProvider.IsAssignable(typeof(CompositeActivity), newBaseType)) 
            { 
                PropertyDescriptor supportsEventsPropDesc = TypeDescriptor.GetProperties(host.RootComponent)["SupportsEvents"];
                if (supportsEventsPropDesc != null && ((bool)supportsEventsPropDesc.GetValue(host.RootComponent)) == true) 
                    supportsEventsPropDesc.SetValue(host.RootComponent, false);

                PropertyDescriptor supportsExceptionsPropDesc = TypeDescriptor.GetProperties(host.RootComponent)["SupportsExceptions"];
                if (supportsExceptionsPropDesc != null && ((bool)supportsExceptionsPropDesc.GetValue(host.RootComponent)) == true) 
                    supportsExceptionsPropDesc.SetValue(host.RootComponent, false);
            } 
 
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(host.RootComponent);
            if (host.RootComponent is CompositeActivity && ((CompositeActivity)host.RootComponent).Activities.Count > 0) 
            {
                // Warn user first if there are any children that can not be re-parented to the new root.
                IUIService uiService = serviceProvider.GetService(typeof(IUIService)) as IUIService;
                if (uiService != null) 
                {
                    if (DialogResult.OK != uiService.ShowMessage(SR.GetString(SR.NoChildActivities_Message), 
                        SR.GetString(SR.NoChildActivities_Caption), MessageBoxButtons.OKCancel)) 
                        return;
                } 

                // Remove the children first. This would cause the component removed event to be fired,
                // thus remove the generated field from the designer.cs file.
                List activitiesToRemove = new List(((CompositeActivity)host.RootComponent).Activities); 
                CompositeActivityDesigner rootDesigner = host.GetDesigner(host.RootComponent) as CompositeActivityDesigner;
                if (rootDesigner != null) 
                    rootDesigner.RemoveActivities(activitiesToRemove.AsReadOnly()); 
            }
 
            //Also, clear all properties of original base. That will allow undo to set old values back.
            foreach (PropertyDescriptor propertyDescriptor in properties)
            {
                if (!propertyDescriptor.Name.Equals("BaseActivityType", StringComparison.Ordinal) && 
                    !propertyDescriptor.Name.Equals("Name", StringComparison.Ordinal) &&
                    propertyDescriptor.CanResetValue(host.RootComponent)) 
                { 
                    propertyDescriptor.ResetValue(host.RootComponent);
                } 
            }

            PropertyDescriptor realBaseActivityTypePropertyDescriptor = properties["BaseActivityType"];
            PropertyDescriptor baseActivityTypePropertyDescriptor = TypeDescriptor.CreateProperty(realBaseActivityTypePropertyDescriptor.ComponentType, realBaseActivityTypePropertyDescriptor, DesignerSerializationVisibilityAttribute.Visible); 

            IComponentChangeService changeService = serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService; 
            if (changeService != null) 
                changeService.OnComponentChanging(host.RootComponent, baseActivityTypePropertyDescriptor);
 
            ((Activity)host.RootComponent).UserData[UserDataKeys.NewBaseType] = newBaseType;

            memberCreationService.UpdateBaseType(host.RootComponentClassName, newBaseType);
 
            if (changeService != null)
                changeService.OnComponentChanged(host.RootComponent, baseActivityTypePropertyDescriptor, baseActivityTypePropertyDescriptor.GetValue(host.RootComponent), typeName); 
 
            //Work around: Force update of the host by raising idle.This is to ensure undo events work on updated host.
            Application.RaiseIdle(new EventArgs()); 
		}

 		private static Type ValidateBaseType(string typeName, IServiceProvider serviceProvider)
 		{ 
			if (typeName != null && typeName.Length > 0)
 			{ 
				ITypeProvider typeProvider = (ITypeProvider)serviceProvider.GetService(typeof(ITypeProvider)); 
				if (typeProvider == null)
					throw new Exception(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); 

 				Type type = typeProvider.GetType(typeName);
				if (type == null)
 					throw new Exception(SR.GetString(SR.Error_TypeNotResolved, typeName)); 

 				IDesignerHost host = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; 
				if (host == null) 
 					throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
 
				Type rootComponentType = typeProvider.GetType(host.RootComponentClassName);

				if (type is DesignTimeType && rootComponentType != null && rootComponentType.Assembly == type.Assembly)
					throw new InvalidOperationException(SR.GetString(SR.Error_CantUseCurrentProjectTypeAsBase)); 

 				if (!TypeProvider.IsAssignable(typeof(Activity), type)) 
					throw new InvalidOperationException(SR.GetString(SR.Error_BaseTypeMustBeActivity)); 

 				return type; 
 			}

			return null;
 		} 

		#endregion 
 
		#region Custom Properties Helper Methods
        internal static List GetCustomProperties(IServiceProvider serviceProvider) 
		{
            // We need to perform a flush just before getting the custom properties so that we are sure that type system is updated
            // and we always get the updated properties
            WorkflowDesignerLoader loader = serviceProvider.GetService(typeof(IDesignerLoaderService)) as WorkflowDesignerLoader; 
            if (loader != null)
                loader.Flush(); 
 
            Type customActivityType = GetCustomActivityType(serviceProvider);
            if (customActivityType == null) 
 				return null;

            List cpc = new List();
			PropertyInfo[] properties = customActivityType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance); 
 			foreach (PropertyInfo property in properties)
 			{ 
				if(property.PropertyType != null) 
 					cpc.Add(CreateCustomProperty(serviceProvider, customActivityType, property, property.PropertyType));
			} 

            EventInfo[] events = customActivityType.GetEvents(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
            foreach (EventInfo evt in events)
            { 
				if (evt.EventHandlerType == null)
					continue; 
                CustomProperty eventProperty = CreateCustomProperty(serviceProvider, customActivityType, evt, evt.EventHandlerType); 
                eventProperty.IsEvent = true;
                cpc.Add(eventProperty); 
            }

 			return cpc;
		} 

        private static CustomProperty CreateCustomProperty(IServiceProvider serviceProvider, Type customActivityType, MemberInfo member, Type propertyType) 
        { 
            CustomProperty customProperty = new CustomProperty(serviceProvider);
            customProperty.Name = member.Name; 
            customProperty.IsEvent = (member is EventInfo);

            if (propertyType == typeof(ActivityBind))
            { 
                customProperty.GenerateDependencyProperty = false;
 				customProperty.Type = typeof(ActivityBind).FullName; 
            } 
            else
            { 
                string fieldSuffix = (customProperty.IsEvent) ? "Event" : "Property";
                FieldInfo fieldInfo = customActivityType.GetField(member.Name + fieldSuffix, BindingFlags.Public | BindingFlags.Static);
                if ((fieldInfo != null && fieldInfo.FieldType == typeof(DependencyProperty)))
                    customProperty.GenerateDependencyProperty = true; 
                else
                    customProperty.GenerateDependencyProperty = false; 
 
                customProperty.Type = propertyType.FullName;
            } 

            customProperty.oldPropertyName = member.Name;
            customProperty.oldPropertyType = propertyType.FullName;
 
            object[] hiddenCodeAttributes = member.GetCustomAttributes(typeof(FlagsAttribute), true);
            if (hiddenCodeAttributes != null && hiddenCodeAttributes.Length > 0) 
                customProperty.Hidden = true; 

            foreach (object attributeObj in member.GetCustomAttributes(false)) 
            {
                AttributeInfoAttribute attribute = attributeObj as AttributeInfoAttribute;
 				AttributeInfo attributeInfo = (attribute != null) ? attribute.AttributeInfo : null;
				if (attributeInfo != null) 
                {
                    try 
                    { 
                        if (attributeInfo.AttributeType == typeof(BrowsableAttribute) && attributeInfo.ArgumentValues.Count > 0)
                        { 
                            customProperty.Browseable = (bool)attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(bool));
                        }
                        else if (attributeInfo.AttributeType == typeof(CategoryAttribute) && attributeInfo.ArgumentValues.Count > 0)
                        { 
                            customProperty.Category = attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(string)) as string;
                        } 
                        else if (attributeInfo.AttributeType == typeof(DescriptionAttribute) && attributeInfo.ArgumentValues.Count > 0) 
                        {
                            customProperty.Description = attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(string)) as string; 
                        }
                        else if (attributeInfo.AttributeType == typeof(DesignerSerializationVisibilityAttribute) && attributeInfo.ArgumentValues.Count > 0)
                        {
                            customProperty.DesignerSerializationVisibility = (DesignerSerializationVisibility)attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(DesignerSerializationVisibility)); 
                        }
                        else if (attributeInfo.AttributeType == typeof(EditorAttribute) && attributeInfo.ArgumentValues.Count > 1) 
                        { 
                            Type editorType = attributeInfo.GetArgumentValueAs(serviceProvider, 1, typeof(Type)) as Type;
                            if (editorType == typeof(UITypeEditor)) 
                            {
                                Type uiTypeEditorType = attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(Type)) as Type;
                                if (uiTypeEditorType != null)
                                    customProperty.UITypeEditor = uiTypeEditorType.FullName; ; 

                                if (String.IsNullOrEmpty(customProperty.UITypeEditor)) 
                                    customProperty.UITypeEditor = attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(string)) as string; 
                            }
                        } 
                    }
                    catch
                    {
                        // Catch and ignore all attribute value conversion errors 
                    }
                } 
            } 

            return customProperty; 
        }


        internal static void SetCustomProperties(List customProperties, IServiceProvider serviceProvider) 
 		{
			if (customProperties == null) 
				throw new ArgumentNullException("customProperties"); 

            Type customActivityType = GetCustomActivityType(serviceProvider); 
            if (customActivityType == null)
				return;

            List existingCustomProperties = GetCustomProperties(serviceProvider); 
 			
			// Remove any deleted properties 
 			RemoveDeletedProperties(customProperties, customActivityType, serviceProvider); 

 			// Add any new properties 
			AddNewProperties(customProperties, customActivityType, serviceProvider, existingCustomProperties);
 		}

        private static void RemoveDeletedProperties(List propCollection, Type customActivityType, IServiceProvider serviceProvider) 
		{
            // 
			IMemberCreationService memberCreationService = serviceProvider.GetService(typeof(IMemberCreationService)) as IMemberCreationService; 
			if (memberCreationService == null)
 				throw new Exception(SR.GetString(SR.General_MissingService, typeof(IMemberCreationService).FullName)); 

			PropertyInfo[] properties = customActivityType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
 			foreach (PropertyInfo property in properties)
 			{ 
				bool found = false;
 				foreach (CustomProperty customProperty in propCollection) 
				{ 
					if (property.Name == customProperty.oldPropertyName &&
						property.PropertyType.FullName == customProperty.oldPropertyType) 
 					{
						found = true;
 						break;
 					} 
				}
 				if (!found) 
					memberCreationService.RemoveProperty(customActivityType.FullName, property.Name, property.PropertyType); 
			}
 
            EventInfo[] events = customActivityType.GetEvents(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
            foreach (EventInfo evtInfo in events)
            {
                bool found = false; 
                foreach (CustomProperty customProperty in propCollection)
                { 
                    if (evtInfo.Name == customProperty.oldPropertyName && 
                        evtInfo.EventHandlerType.FullName == customProperty.oldPropertyType)
                    { 
                        found = true;
                        break;
                    }
                } 
                if (!found && evtInfo.Name != null && evtInfo.EventHandlerType != null)
                    memberCreationService.RemoveEvent(customActivityType.FullName, evtInfo.Name, evtInfo.EventHandlerType); 
            } 
		}
 
        private static void AddNewProperties(List propCollection, Type customActivityType, IServiceProvider serviceProvider, List existingProps)
 		{
			IMemberCreationService memberCreationService = serviceProvider.GetService(typeof(IMemberCreationService)) as IMemberCreationService;
 			if (memberCreationService == null) 
 				throw new Exception(SR.GetString(SR.General_MissingService, typeof(IMemberCreationService).FullName));
 
			ITypeProvider typeProvider = serviceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider; 
 			if (typeProvider == null)
				throw new Exception(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); 

			try
			{
 				// 

  
 
 				foreach (CustomProperty property in propCollection)
				{ 
                    bool createNew = (property.oldPropertyName == null || property.oldPropertyType == null);
                    if (!createNew)
                    {
                        if (!property.IsEvent) 
                            createNew = (customActivityType.GetProperty(property.oldPropertyName, typeProvider.GetType(property.oldPropertyType)) == null);
                        else 
                            createNew = (customActivityType.GetEvent(property.oldPropertyName) == null); 
                    }
 
                    if (createNew)
                    {
                        AttributeInfo[] attributes = CreateCustomPropertyAttributeArray(property, serviceProvider);
                        if (property.IsEvent) 
                            memberCreationService.CreateEvent(customActivityType.FullName, property.Name, typeProvider.GetType(property.Type), attributes, property.GenerateDependencyProperty);
                        else 
                            memberCreationService.CreateProperty(customActivityType.FullName, property.Name, typeProvider.GetType(property.Type), attributes, property.GenerateDependencyProperty, false, false, null, false); 
                    }
                    else 
                    {
                        //

                        CustomProperty oldProperty = null; 
                        foreach (CustomProperty existingProperty in existingProps)
                        { 
                            if (existingProperty.Name == property.oldPropertyName && existingProperty.Type == property.oldPropertyType) 
                                oldProperty = existingProperty;
                        } 

                        if (oldProperty == null || ArePropertiesDifferent(property, oldProperty))
                        {
                            AttributeInfo[] attributes = CreateCustomPropertyAttributeArray(property, serviceProvider); 
                            AttributeInfo[] oldAttributes = CreateCustomPropertyAttributeArray(oldProperty, serviceProvider);
 
                            Type propertyType = typeProvider.GetType(property.Type, false); 
                            Type oldPropertyType = typeProvider.GetType(property.oldPropertyType, false);
                            if (propertyType != null) 
                            {
                                if (property.IsEvent)
                                    memberCreationService.UpdateEvent(customActivityType.FullName, property.oldPropertyName, oldPropertyType, property.Name, propertyType, attributes, property.GenerateDependencyProperty, false);
                                else 
                                    memberCreationService.UpdateProperty(customActivityType.FullName, property.oldPropertyName, oldPropertyType, property.Name, propertyType, attributes, property.GenerateDependencyProperty, false);
                            } 
                        } 
                    }	
 				} 
			}
			finally
			{
 				// 

  
 			} 
		}
 
 		private static AttributeInfo[] CreateCustomPropertyAttributeArray(CustomProperty property, IServiceProvider serviceProvider)
		{
			// Don't generate these attributes for hidden properties, just let the
			// attributes that already exist on the property stay 
 			if (property == null || property.Hidden)
				return new AttributeInfo[0]; 
 
 			List attributeList = new List();
 
 			if (property.Category != null)
				attributeList.Add(new AttributeInfo(typeof(CategoryAttribute), new string[] { }, new object[] { new CodePrimitiveExpression(property.Category) }));

 			if (property.Description != null) 
				attributeList.Add(new AttributeInfo(typeof(DescriptionAttribute), new string[] { }, new object[] { new CodePrimitiveExpression(property.Description) }));
 
			if (!string.IsNullOrEmpty(property.UITypeEditor)) 
				attributeList.Add(new AttributeInfo(typeof(EditorAttribute), new string[] { }, new object[] { new CodeTypeOfExpression(property.UITypeEditor), new CodeTypeOfExpression(typeof(UITypeEditor)) }));
 
 			attributeList.Add(new AttributeInfo(typeof(BrowsableAttribute), new string[] { }, new object[] { new CodePrimitiveExpression(property.Browseable) }));
			attributeList.Add(new AttributeInfo(typeof(DesignerSerializationVisibilityAttribute), new string[] { }, new object[] { new CodeSnippetExpression(typeof(DesignerSerializationVisibility).Name + "." + property.DesignerSerializationVisibility.ToString()) }));

 			return attributeList.ToArray(); 
 		}
 
		private static bool ArePropertiesDifferent(CustomProperty property, CustomProperty oldProperty) 
 		{
			if (property.Name == oldProperty.Name && 
				property.Type == oldProperty.Type &&
				property.Browseable == oldProperty.Browseable &&
 				property.Category == oldProperty.Category &&
				property.Description == oldProperty.Description && 
 				property.DesignerSerializationVisibility == oldProperty.DesignerSerializationVisibility &&
 				property.Hidden == oldProperty.Hidden && 
				property.UITypeEditor == oldProperty.UITypeEditor) 
 			{
				return false; 
			}

			return true;
 		} 
		#endregion
 	} 
    #endregion 

 	#region Class BaseClassTypeFilterProvider 
	internal sealed class BaseClassTypeFilterProvider : ITypeFilterProvider
    {
 		private IServiceProvider serviceProvider;
 
        public BaseClassTypeFilterProvider(IServiceProvider serviceProvider)
        { 
			this.serviceProvider = serviceProvider; 
        }
 
        #region ITypeFilterProvider Members
        bool ITypeFilterProvider.CanFilterType(Type type, bool throwOnError)
        {
			bool filterType = false; 
			if (TypeProvider.IsAssignable(typeof(Activity), type) && type.IsPublic && !type.IsSealed && !type.IsAbstract && !(type is DesignTimeType))
 			{ 
                filterType = true; 
			}
 
 			return filterType;
        }

        string ITypeFilterProvider.FilterDescription 
        {
            get 
            { 
                return SR.GetString(SR.CustomActivityBaseClassTypeFilterProviderDesc);
            } 
        }
        #endregion
    }
    #endregion 

    #region CustomProperties 
    internal sealed class CustomProperty 
    {
        public string oldPropertyName; 
        public string oldPropertyType;
        private string name;
        private string type;
        private string category; 
        private string description;
        private DesignerSerializationVisibility designerSerializationVisibility = DesignerSerializationVisibility.Visible; 
        // NOTE: we don't write the ValidationOption attribute anymore (WinOE Bug 17398). We have removed our property creation 
        // dialog in beta1.  Now this code is only used for property promotion.  If the promoted property is a meta property,
        // it can not be bindable so no promotion is not allowed.  If the property is an instance property, this attribute is ignored. 
        // There is no reason for writing out this attribute anymore.We just remove it from property promotion all together.
        // NOTE II: for the same reason that this code is only used for promotion, we don't write out meta properties anymore.
        // We had customized the CodeDomSerializer.Deserialize to recognize meta properties by inspecting the field init expression,
        // which is no long needed.  If we were to bring this functionality back in the future, sample code can be found 
        // from the file history in Source Depot.
        private bool isEvent = false; 
        private bool browseable = true; 
        private bool hidden = false;
        private string uiTypeEditor; 
        private IServiceProvider serviceProvider = null;
        private bool generateDependencyProperty = true;

        public CustomProperty(IServiceProvider serviceProvider) 
        {
            this.serviceProvider = serviceProvider; 
        } 

        public string Name 
        {
            get
            {
                return this.name; 
            }
            set 
            { 
                this.name = value;
            } 
        }

        public string Type
        { 
            get
            { 
                return this.type; 
            }
            set 
            {
                this.type = value;
            }
        } 

        public string Description 
        { 
            get
            { 
                return this.description;
            }
            set
            { 
                this.description = value;
            } 
        } 

        public string Category 
        {
            get
            {
                return this.category; 
            }
            set 
            { 
                this.category = value;
            } 
        }

        public bool Browseable
        { 
            get
            { 
                return this.browseable; 
            }
            set 
            {
                this.browseable = value;
            }
        } 

        public DesignerSerializationVisibility DesignerSerializationVisibility 
        { 
            get
            { 
                return this.designerSerializationVisibility;
            }
            set
            { 
                this.designerSerializationVisibility = value;
            } 
        } 

        public string UITypeEditor 
        {
            get
            {
                return this.uiTypeEditor; 
            }
            set 
            { 
                string typeName = value;
 
                // Try to make sure the type is specified witht he fullName;
                if (this.serviceProvider != null)
                {
                    ITypeProvider typeProvider = this.serviceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider; 
                    if (typeProvider == null)
                        throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); 
 
                    Type type = typeProvider.GetType(typeName);
                    if (type != null) 
                        typeName = type.FullName;
                }

                this.uiTypeEditor = typeName; 
            }
        } 
 
        public bool IsEvent
        { 
            get
            {
                return this.isEvent;
            } 
            set
            { 
                this.isEvent = value; 
            }
        } 

        public bool Hidden
        {
            get 
            {
                return this.hidden; 
            } 
            set
            { 
                this.hidden = value;
            }
        }
 
        public bool GenerateDependencyProperty
        { 
            get 
            {
                return this.generateDependencyProperty; 
            }

            set
            { 
                this.generateDependencyProperty = value;
            } 
        } 

        #region Private Helpers 
        public static CustomProperty CreateCustomProperty(IServiceProvider serviceProvider, string customPropertyName, PropertyDescriptor propertyDescriptor, object propertyOwner)
        {
            CustomProperty newCustomProperty = new CustomProperty(serviceProvider);
            newCustomProperty.Name = customPropertyName; 
            if (TypeProvider.IsAssignable(typeof(ActivityBind), propertyDescriptor.PropertyType))
            { 
                Type baseType = PropertyDescriptorUtils.GetBaseType(propertyDescriptor, propertyOwner, serviceProvider); 
                if (baseType == null)
                    throw new InvalidOperationException(SR.GetString(SR.Error_CantDeterminePropertyBaseType, propertyDescriptor.Name)); 
                newCustomProperty.Type = baseType.FullName;
            }
            else
            { 
                newCustomProperty.Type = propertyDescriptor.PropertyType.FullName;
            } 
 
            if (propertyDescriptor is ActivityBindPropertyDescriptor)
            { 
                DependencyProperty dependencyProperty = DependencyProperty.FromName(propertyDescriptor.Name, propertyDescriptor.ComponentType);
                newCustomProperty.IsEvent = (dependencyProperty != null && dependencyProperty.IsEvent);
            }
 
            newCustomProperty.Category = propertyDescriptor.Category;
            return newCustomProperty; 
        } 
        #endregion
    } 
    #endregion

}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
´╗┐namespace System.Workflow.ComponentModel.Design 
{
    #region Using directives

    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Text; 
    using System.ComponentModel;
    using System.Drawing.Design; 
    using System.ComponentModel.Design;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Compiler;
    using System.Globalization; 
    using System.Reflection;
    using System.Reflection.Emit; 
    using System.ComponentModel.Design.Serialization; 
    using System.Windows.Forms;
    using System.Windows.Forms.Design; 
    using System.CodeDom;

    #endregion
 
    #region Class CustomActivityDesignerAdapter
 
 	internal sealed class CustomActivityDesignerAdapter : IDisposable 
    {
        private IServiceProvider								serviceProvider = null; 
		private EventHandler									ensureChildHierarchyHandler = null;

        public CustomActivityDesignerAdapter(IServiceProvider serviceProvider)
        { 
            this.serviceProvider = serviceProvider;
 
            IComponentChangeService componentChangeService = this.serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService; 
            if (componentChangeService != null)
            { 
                componentChangeService.ComponentAdding += new ComponentEventHandler(OnComponentAdding);
                componentChangeService.ComponentAdded += new ComponentEventHandler(OnComponentAdded);
            }
        } 

        void IDisposable.Dispose() 
        { 
            if (this.ensureChildHierarchyHandler != null)
            { 
                Application.Idle -= this.ensureChildHierarchyHandler;
                this.ensureChildHierarchyHandler = null;
            }
 
            IComponentChangeService componentChangeService = this.serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
            if (componentChangeService != null) 
            { 
                componentChangeService.ComponentAdding -= new ComponentEventHandler(OnComponentAdding);
                componentChangeService.ComponentAdded -= new ComponentEventHandler(OnComponentAdded); 
            }
        }

        #region Helpers 
        private void OnComponentAdding(object sender, ComponentEventArgs eventArgs)
        { 
            //We are adding root component, while doing this make sure that we provide the root designer attribute 
            IDesignerHost designerHost = (IDesignerHost)this.serviceProvider.GetService(typeof(IDesignerHost));
            if (designerHost != null) 
            {
                if (designerHost.RootComponent == null)
                {
                    Activity rootActivity = eventArgs.Component as Activity; 
                    if (rootActivity != null)
                    { 
                        //Add root designer attribute 
                        DesignerAttribute rootDesignerAttrib = GetDesignerAttribute(rootActivity, typeof(IRootDesigner));
                        if (rootDesignerAttrib.DesignerTypeName == typeof(ActivityDesigner).AssemblyQualifiedName) 
                        {
                            DesignerAttribute designerAttrib = GetDesignerAttribute(rootActivity, typeof(IDesigner));
                            if (designerAttrib != null)
                                TypeDescriptor.AddAttributes(rootActivity, new Attribute[] { new DesignerAttribute(designerAttrib.DesignerTypeName, typeof(IRootDesigner)) }); 
                        }
                    } 
                } 
            }
        } 

        private void OnComponentAdded(object sender, ComponentEventArgs eventArgs)
        {
            IDesignerHost designerHost = (IDesignerHost)this.serviceProvider.GetService(typeof(IDesignerHost)); 
            if (designerHost != null)
            { 
                if (designerHost.RootComponent == eventArgs.Component) 
                {
                    Activity rootActivity = designerHost.RootComponent as Activity; 
                    if (rootActivity != null)
                    {
                        CompositeActivity compositeActivity = rootActivity as CompositeActivity;
                        if (compositeActivity != null) 
                        {
                            if (this.ensureChildHierarchyHandler == null) 
                            { 
                                this.ensureChildHierarchyHandler = new EventHandler(OnEnsureChildHierarchy);
                                Application.Idle += this.ensureChildHierarchyHandler; 
                            }
                        }
                        rootActivity.UserData[UserDataKeys.CustomActivity] = false;
                    } 
                }
                else if (eventArgs.Component is Activity) 
                { 
                    if ((eventArgs.Component is CompositeActivity) && Helpers.IsCustomActivity(eventArgs.Component as CompositeActivity))
                        (eventArgs.Component as Activity).UserData[UserDataKeys.CustomActivity] = true; 
                    else
                        (eventArgs.Component as Activity).UserData[UserDataKeys.CustomActivity] = false;
                }
            } 
        }
 
        ///PLEASE NOTE: We have added this handler for a reason. When the user changes the base type of the Activity 
        ///we reload the designer after flushing the changes to the buffer, we do that in the IDesignerHost.TransactionClosed event
        /// The reload of the designer is then done on Idle event; but during reload we add extra components in the composite activity 
        /// which in short modifies the composite activity,but during loading process the BasicDesignerLoader ignores such modification and
        /// does not tag the buffer as modified. The problem which happens due to this is that we wont flush the changes caused by
        /// adding of additional components to the buffer there by not saving the child designers. Hence instead of adding components during reload
        /// we add them in the first idle event after reload. 
        private void OnEnsureChildHierarchy(object sender, EventArgs e)
        { 
            if (this.ensureChildHierarchyHandler != null) 
            {
                Application.Idle -= this.ensureChildHierarchyHandler; 
                this.ensureChildHierarchyHandler = null;

                IDesignerHost designerHost = (IDesignerHost)this.serviceProvider.GetService(typeof(IDesignerHost));
                if (designerHost != null) 
                    EnsureDefaultChildHierarchy(designerHost);
            } 
        } 

        private static DesignerAttribute GetDesignerAttribute(object component, Type designerBaseType) 
        {
            AttributeCollection attribs = TypeDescriptor.GetAttributes(component);
            foreach (Attribute attribute in attribs)
            { 
                DesignerAttribute designerAttribute = attribute as DesignerAttribute;
                if (designerAttribute != null && designerAttribute.DesignerBaseTypeName == designerBaseType.AssemblyQualifiedName) 
                    return designerAttribute; 
            }
 
            return null;
        }

		private static void EnsureDefaultChildHierarchy(IDesignerHost designerHost) 
		{
            //When we are adding the root activity we need to make sure that all the child activities which are required by the parent 
            //activity are looked up in the toolboxitem and added appropriately 
            //If the composite activity already has a some child activities but not all then it
            //means that user has changed the InitializeComponent and hence we do nothing 
            //This is the simple check to get the designer working in case of selecting composite
            //root activities
            CompositeActivity rootActivity = designerHost.RootComponent as CompositeActivity;
            if (rootActivity != null && rootActivity.Activities.Count == 0) 
            {
 				object[] attribs = rootActivity.GetType().GetCustomAttributes(typeof(ToolboxItemAttribute), false); 
                ToolboxItemAttribute toolboxItemAttrib = (attribs != null && attribs.GetLength(0) > 0) ? attribs[0] as ToolboxItemAttribute : null; 
                if (toolboxItemAttrib != null && toolboxItemAttrib.ToolboxItemType != null)
                { 
					ToolboxItem item = Activator.CreateInstance(toolboxItemAttrib.ToolboxItemType, new object[] { rootActivity.GetType() }) as ToolboxItem;
                    IComponent[] components = item.CreateComponents();

                    //I am assuming here that there will be always one top level component created. 
                    //If there are multiple then there is a bigger problem as we dont know how
                    //to use those 
                    CompositeActivity compositeActivity = null; 
                    foreach (IComponent component in components)
                    { 
 						if (component.GetType() == rootActivity.GetType())
                        {
                            compositeActivity = component as CompositeActivity;
                            break; 
                        }
                    } 
 
                    //Add the children
                    if (compositeActivity != null && compositeActivity.Activities.Count > 0) 
                    {
                        IIdentifierCreationService identifierCreationService = designerHost.GetService(typeof(IIdentifierCreationService)) as IIdentifierCreationService;
                        if (identifierCreationService != null)
                        { 
                            //We do not go thru the composite designer here as composite activity
                            //might have simple designer 
                            Activity[] activities = compositeActivity.Activities.ToArray(); 
                            compositeActivity.Activities.Clear();
 
                            identifierCreationService.EnsureUniqueIdentifiers(rootActivity, activities);
 							// Work around : Don't called AddRange because it doesn't send the ListChange notifications
							// to the activity collection.  Use multiple Add calls instaead
 							foreach (Activity newActivity in activities) 
								rootActivity.Activities.Add(newActivity);
 
                            foreach (Activity childActivity in activities) 
                                WorkflowDesignerLoader.AddActivityToDesigner(designerHost, childActivity);
                        } 
                    }
                }
            }
        } 
        #endregion
    } 
    #endregion 

    #region Extenders 

    #region Class CustomActivityPropertyExtender
    [ProvideProperty("BaseActivityType", typeof(Activity))]
    internal sealed class CustomActivityPropertyExtender : IExtenderProvider 
    {
        public CustomActivityPropertyExtender() 
        { 
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [SRDisplayName(SR.BaseActivityType)]
		[SRCategory(SR.ActivityDesc)]
		[SRDescription(SR.CustomActivityBaseTypeDesc)] 
 		[Editor(typeof(TypeBrowserEditor), typeof(UITypeEditor))]
		[DesignOnly(true)] 
 		[TypeFilterProvider(typeof(BaseClassTypeFilterProvider))] 
        [DefaultValue("System.Workflow.ComponentModel.Sequence")]
 		public string GetBaseActivityType(Activity activity) 
		{
            // The activity type will be the base type.  No need for more complicated logic here.
            return activity.GetType().FullName;
        } 

 		//Do not remove this function, it is being called indirectly 
        public void SetBaseActivityType(Activity activity, string baseActivityTypeName) 
        {
            CustomActivityDesignerHelper.SetBaseTypeName(baseActivityTypeName, activity.Site); 

			// Once the base type is changed, cause each of the companion class properties
			// to set their value again, updating their base types appropriatly
		} 

        bool IExtenderProvider.CanExtend(object extendee) 
        { 
            bool canExtend = false;
 
            Activity activity = extendee as Activity;
            if (activity != null && activity.Site != null && activity == Helpers.GetRootActivity(activity))
            {
                ActivityDesigner rootDesigner = ActivityDesigner.GetDesigner(activity); 
                if (rootDesigner != null && rootDesigner.ParentDesigner == null)
                    canExtend = true; 
            } 

            return canExtend; 
        }
    }
    #endregion
 
    #endregion
 
    #region Class CustomActivityDesignerHelper 
    internal static class CustomActivityDesignerHelper
 	{ 
		#region Base Type Helper Methods
        public static Type GetCustomActivityType(IServiceProvider serviceProvider)
        {
 			IDesignerHost host = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; 
 			if (host == null)
				throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName)); 
 
 			string className = host.RootComponentClassName;
            if (string.IsNullOrEmpty(className)) 
                return null;

			ITypeProvider typeProvider = serviceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider;
			if (typeProvider == null) 
				throw new Exception(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
 
            return typeProvider.GetType(className, false); 
        }
 
 		public static void SetBaseTypeName(string typeName, IServiceProvider serviceProvider)
		{
 			if (string.IsNullOrEmpty(typeName))
 				throw new ArgumentNullException("typeName"); 

            IDesignerHost host = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; 
            if (host == null) 
                throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
 
            IMemberCreationService memberCreationService = serviceProvider.GetService(typeof(IMemberCreationService)) as IMemberCreationService;
            if (memberCreationService == null)
                throw new InvalidOperationException(SR.GetString("General_MissingService", typeof(IMemberCreationService).FullName));
 
			// Validate the base type (this will throw an exception if the type name isn't valid
 			Type newBaseType = ValidateBaseType(typeName, serviceProvider); 
 
			//Warn the user of the change
			Type oldBaseType = host.RootComponent.GetType(); 
			if (oldBaseType == newBaseType)
 				return;

            // If we're switch to a base type that is not derived from CompositeActivity, make sure 
            // we dont's support events or exceptions
            if (!TypeProvider.IsAssignable(typeof(CompositeActivity), newBaseType)) 
            { 
                PropertyDescriptor supportsEventsPropDesc = TypeDescriptor.GetProperties(host.RootComponent)["SupportsEvents"];
                if (supportsEventsPropDesc != null && ((bool)supportsEventsPropDesc.GetValue(host.RootComponent)) == true) 
                    supportsEventsPropDesc.SetValue(host.RootComponent, false);

                PropertyDescriptor supportsExceptionsPropDesc = TypeDescriptor.GetProperties(host.RootComponent)["SupportsExceptions"];
                if (supportsExceptionsPropDesc != null && ((bool)supportsExceptionsPropDesc.GetValue(host.RootComponent)) == true) 
                    supportsExceptionsPropDesc.SetValue(host.RootComponent, false);
            } 
 
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(host.RootComponent);
            if (host.RootComponent is CompositeActivity && ((CompositeActivity)host.RootComponent).Activities.Count > 0) 
            {
                // Warn user first if there are any children that can not be re-parented to the new root.
                IUIService uiService = serviceProvider.GetService(typeof(IUIService)) as IUIService;
                if (uiService != null) 
                {
                    if (DialogResult.OK != uiService.ShowMessage(SR.GetString(SR.NoChildActivities_Message), 
                        SR.GetString(SR.NoChildActivities_Caption), MessageBoxButtons.OKCancel)) 
                        return;
                } 

                // Remove the children first. This would cause the component removed event to be fired,
                // thus remove the generated field from the designer.cs file.
                List activitiesToRemove = new List(((CompositeActivity)host.RootComponent).Activities); 
                CompositeActivityDesigner rootDesigner = host.GetDesigner(host.RootComponent) as CompositeActivityDesigner;
                if (rootDesigner != null) 
                    rootDesigner.RemoveActivities(activitiesToRemove.AsReadOnly()); 
            }
 
            //Also, clear all properties of original base. That will allow undo to set old values back.
            foreach (PropertyDescriptor propertyDescriptor in properties)
            {
                if (!propertyDescriptor.Name.Equals("BaseActivityType", StringComparison.Ordinal) && 
                    !propertyDescriptor.Name.Equals("Name", StringComparison.Ordinal) &&
                    propertyDescriptor.CanResetValue(host.RootComponent)) 
                { 
                    propertyDescriptor.ResetValue(host.RootComponent);
                } 
            }

            PropertyDescriptor realBaseActivityTypePropertyDescriptor = properties["BaseActivityType"];
            PropertyDescriptor baseActivityTypePropertyDescriptor = TypeDescriptor.CreateProperty(realBaseActivityTypePropertyDescriptor.ComponentType, realBaseActivityTypePropertyDescriptor, DesignerSerializationVisibilityAttribute.Visible); 

            IComponentChangeService changeService = serviceProvider.GetService(typeof(IComponentChangeService)) as IComponentChangeService; 
            if (changeService != null) 
                changeService.OnComponentChanging(host.RootComponent, baseActivityTypePropertyDescriptor);
 
            ((Activity)host.RootComponent).UserData[UserDataKeys.NewBaseType] = newBaseType;

            memberCreationService.UpdateBaseType(host.RootComponentClassName, newBaseType);
 
            if (changeService != null)
                changeService.OnComponentChanged(host.RootComponent, baseActivityTypePropertyDescriptor, baseActivityTypePropertyDescriptor.GetValue(host.RootComponent), typeName); 
 
            //Work around: Force update of the host by raising idle.This is to ensure undo events work on updated host.
            Application.RaiseIdle(new EventArgs()); 
		}

 		private static Type ValidateBaseType(string typeName, IServiceProvider serviceProvider)
 		{ 
			if (typeName != null && typeName.Length > 0)
 			{ 
				ITypeProvider typeProvider = (ITypeProvider)serviceProvider.GetService(typeof(ITypeProvider)); 
				if (typeProvider == null)
					throw new Exception(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); 

 				Type type = typeProvider.GetType(typeName);
				if (type == null)
 					throw new Exception(SR.GetString(SR.Error_TypeNotResolved, typeName)); 

 				IDesignerHost host = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; 
				if (host == null) 
 					throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
 
				Type rootComponentType = typeProvider.GetType(host.RootComponentClassName);

				if (type is DesignTimeType && rootComponentType != null && rootComponentType.Assembly == type.Assembly)
					throw new InvalidOperationException(SR.GetString(SR.Error_CantUseCurrentProjectTypeAsBase)); 

 				if (!TypeProvider.IsAssignable(typeof(Activity), type)) 
					throw new InvalidOperationException(SR.GetString(SR.Error_BaseTypeMustBeActivity)); 

 				return type; 
 			}

			return null;
 		} 

		#endregion 
 
		#region Custom Properties Helper Methods
        internal static List GetCustomProperties(IServiceProvider serviceProvider) 
		{
            // We need to perform a flush just before getting the custom properties so that we are sure that type system is updated
            // and we always get the updated properties
            WorkflowDesignerLoader loader = serviceProvider.GetService(typeof(IDesignerLoaderService)) as WorkflowDesignerLoader; 
            if (loader != null)
                loader.Flush(); 
 
            Type customActivityType = GetCustomActivityType(serviceProvider);
            if (customActivityType == null) 
 				return null;

            List cpc = new List();
			PropertyInfo[] properties = customActivityType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance); 
 			foreach (PropertyInfo property in properties)
 			{ 
				if(property.PropertyType != null) 
 					cpc.Add(CreateCustomProperty(serviceProvider, customActivityType, property, property.PropertyType));
			} 

            EventInfo[] events = customActivityType.GetEvents(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
            foreach (EventInfo evt in events)
            { 
				if (evt.EventHandlerType == null)
					continue; 
                CustomProperty eventProperty = CreateCustomProperty(serviceProvider, customActivityType, evt, evt.EventHandlerType); 
                eventProperty.IsEvent = true;
                cpc.Add(eventProperty); 
            }

 			return cpc;
		} 

        private static CustomProperty CreateCustomProperty(IServiceProvider serviceProvider, Type customActivityType, MemberInfo member, Type propertyType) 
        { 
            CustomProperty customProperty = new CustomProperty(serviceProvider);
            customProperty.Name = member.Name; 
            customProperty.IsEvent = (member is EventInfo);

            if (propertyType == typeof(ActivityBind))
            { 
                customProperty.GenerateDependencyProperty = false;
 				customProperty.Type = typeof(ActivityBind).FullName; 
            } 
            else
            { 
                string fieldSuffix = (customProperty.IsEvent) ? "Event" : "Property";
                FieldInfo fieldInfo = customActivityType.GetField(member.Name + fieldSuffix, BindingFlags.Public | BindingFlags.Static);
                if ((fieldInfo != null && fieldInfo.FieldType == typeof(DependencyProperty)))
                    customProperty.GenerateDependencyProperty = true; 
                else
                    customProperty.GenerateDependencyProperty = false; 
 
                customProperty.Type = propertyType.FullName;
            } 

            customProperty.oldPropertyName = member.Name;
            customProperty.oldPropertyType = propertyType.FullName;
 
            object[] hiddenCodeAttributes = member.GetCustomAttributes(typeof(FlagsAttribute), true);
            if (hiddenCodeAttributes != null && hiddenCodeAttributes.Length > 0) 
                customProperty.Hidden = true; 

            foreach (object attributeObj in member.GetCustomAttributes(false)) 
            {
                AttributeInfoAttribute attribute = attributeObj as AttributeInfoAttribute;
 				AttributeInfo attributeInfo = (attribute != null) ? attribute.AttributeInfo : null;
				if (attributeInfo != null) 
                {
                    try 
                    { 
                        if (attributeInfo.AttributeType == typeof(BrowsableAttribute) && attributeInfo.ArgumentValues.Count > 0)
                        { 
                            customProperty.Browseable = (bool)attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(bool));
                        }
                        else if (attributeInfo.AttributeType == typeof(CategoryAttribute) && attributeInfo.ArgumentValues.Count > 0)
                        { 
                            customProperty.Category = attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(string)) as string;
                        } 
                        else if (attributeInfo.AttributeType == typeof(DescriptionAttribute) && attributeInfo.ArgumentValues.Count > 0) 
                        {
                            customProperty.Description = attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(string)) as string; 
                        }
                        else if (attributeInfo.AttributeType == typeof(DesignerSerializationVisibilityAttribute) && attributeInfo.ArgumentValues.Count > 0)
                        {
                            customProperty.DesignerSerializationVisibility = (DesignerSerializationVisibility)attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(DesignerSerializationVisibility)); 
                        }
                        else if (attributeInfo.AttributeType == typeof(EditorAttribute) && attributeInfo.ArgumentValues.Count > 1) 
                        { 
                            Type editorType = attributeInfo.GetArgumentValueAs(serviceProvider, 1, typeof(Type)) as Type;
                            if (editorType == typeof(UITypeEditor)) 
                            {
                                Type uiTypeEditorType = attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(Type)) as Type;
                                if (uiTypeEditorType != null)
                                    customProperty.UITypeEditor = uiTypeEditorType.FullName; ; 

                                if (String.IsNullOrEmpty(customProperty.UITypeEditor)) 
                                    customProperty.UITypeEditor = attributeInfo.GetArgumentValueAs(serviceProvider, 0, typeof(string)) as string; 
                            }
                        } 
                    }
                    catch
                    {
                        // Catch and ignore all attribute value conversion errors 
                    }
                } 
            } 

            return customProperty; 
        }


        internal static void SetCustomProperties(List customProperties, IServiceProvider serviceProvider) 
 		{
			if (customProperties == null) 
				throw new ArgumentNullException("customProperties"); 

            Type customActivityType = GetCustomActivityType(serviceProvider); 
            if (customActivityType == null)
				return;

            List existingCustomProperties = GetCustomProperties(serviceProvider); 
 			
			// Remove any deleted properties 
 			RemoveDeletedProperties(customProperties, customActivityType, serviceProvider); 

 			// Add any new properties 
			AddNewProperties(customProperties, customActivityType, serviceProvider, existingCustomProperties);
 		}

        private static void RemoveDeletedProperties(List propCollection, Type customActivityType, IServiceProvider serviceProvider) 
		{
            // 
			IMemberCreationService memberCreationService = serviceProvider.GetService(typeof(IMemberCreationService)) as IMemberCreationService; 
			if (memberCreationService == null)
 				throw new Exception(SR.GetString(SR.General_MissingService, typeof(IMemberCreationService).FullName)); 

			PropertyInfo[] properties = customActivityType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
 			foreach (PropertyInfo property in properties)
 			{ 
				bool found = false;
 				foreach (CustomProperty customProperty in propCollection) 
				{ 
					if (property.Name == customProperty.oldPropertyName &&
						property.PropertyType.FullName == customProperty.oldPropertyType) 
 					{
						found = true;
 						break;
 					} 
				}
 				if (!found) 
					memberCreationService.RemoveProperty(customActivityType.FullName, property.Name, property.PropertyType); 
			}
 
            EventInfo[] events = customActivityType.GetEvents(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
            foreach (EventInfo evtInfo in events)
            {
                bool found = false; 
                foreach (CustomProperty customProperty in propCollection)
                { 
                    if (evtInfo.Name == customProperty.oldPropertyName && 
                        evtInfo.EventHandlerType.FullName == customProperty.oldPropertyType)
                    { 
                        found = true;
                        break;
                    }
                } 
                if (!found && evtInfo.Name != null && evtInfo.EventHandlerType != null)
                    memberCreationService.RemoveEvent(customActivityType.FullName, evtInfo.Name, evtInfo.EventHandlerType); 
            } 
		}
 
        private static void AddNewProperties(List propCollection, Type customActivityType, IServiceProvider serviceProvider, List existingProps)
 		{
			IMemberCreationService memberCreationService = serviceProvider.GetService(typeof(IMemberCreationService)) as IMemberCreationService;
 			if (memberCreationService == null) 
 				throw new Exception(SR.GetString(SR.General_MissingService, typeof(IMemberCreationService).FullName));
 
			ITypeProvider typeProvider = serviceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider; 
 			if (typeProvider == null)
				throw new Exception(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); 

			try
			{
 				// 

  
 
 				foreach (CustomProperty property in propCollection)
				{ 
                    bool createNew = (property.oldPropertyName == null || property.oldPropertyType == null);
                    if (!createNew)
                    {
                        if (!property.IsEvent) 
                            createNew = (customActivityType.GetProperty(property.oldPropertyName, typeProvider.GetType(property.oldPropertyType)) == null);
                        else 
                            createNew = (customActivityType.GetEvent(property.oldPropertyName) == null); 
                    }
 
                    if (createNew)
                    {
                        AttributeInfo[] attributes = CreateCustomPropertyAttributeArray(property, serviceProvider);
                        if (property.IsEvent) 
                            memberCreationService.CreateEvent(customActivityType.FullName, property.Name, typeProvider.GetType(property.Type), attributes, property.GenerateDependencyProperty);
                        else 
                            memberCreationService.CreateProperty(customActivityType.FullName, property.Name, typeProvider.GetType(property.Type), attributes, property.GenerateDependencyProperty, false, false, null, false); 
                    }
                    else 
                    {
                        //

                        CustomProperty oldProperty = null; 
                        foreach (CustomProperty existingProperty in existingProps)
                        { 
                            if (existingProperty.Name == property.oldPropertyName && existingProperty.Type == property.oldPropertyType) 
                                oldProperty = existingProperty;
                        } 

                        if (oldProperty == null || ArePropertiesDifferent(property, oldProperty))
                        {
                            AttributeInfo[] attributes = CreateCustomPropertyAttributeArray(property, serviceProvider); 
                            AttributeInfo[] oldAttributes = CreateCustomPropertyAttributeArray(oldProperty, serviceProvider);
 
                            Type propertyType = typeProvider.GetType(property.Type, false); 
                            Type oldPropertyType = typeProvider.GetType(property.oldPropertyType, false);
                            if (propertyType != null) 
                            {
                                if (property.IsEvent)
                                    memberCreationService.UpdateEvent(customActivityType.FullName, property.oldPropertyName, oldPropertyType, property.Name, propertyType, attributes, property.GenerateDependencyProperty, false);
                                else 
                                    memberCreationService.UpdateProperty(customActivityType.FullName, property.oldPropertyName, oldPropertyType, property.Name, propertyType, attributes, property.GenerateDependencyProperty, false);
                            } 
                        } 
                    }	
 				} 
			}
			finally
			{
 				// 

  
 			} 
		}
 
 		private static AttributeInfo[] CreateCustomPropertyAttributeArray(CustomProperty property, IServiceProvider serviceProvider)
		{
			// Don't generate these attributes for hidden properties, just let the
			// attributes that already exist on the property stay 
 			if (property == null || property.Hidden)
				return new AttributeInfo[0]; 
 
 			List attributeList = new List();
 
 			if (property.Category != null)
				attributeList.Add(new AttributeInfo(typeof(CategoryAttribute), new string[] { }, new object[] { new CodePrimitiveExpression(property.Category) }));

 			if (property.Description != null) 
				attributeList.Add(new AttributeInfo(typeof(DescriptionAttribute), new string[] { }, new object[] { new CodePrimitiveExpression(property.Description) }));
 
			if (!string.IsNullOrEmpty(property.UITypeEditor)) 
				attributeList.Add(new AttributeInfo(typeof(EditorAttribute), new string[] { }, new object[] { new CodeTypeOfExpression(property.UITypeEditor), new CodeTypeOfExpression(typeof(UITypeEditor)) }));
 
 			attributeList.Add(new AttributeInfo(typeof(BrowsableAttribute), new string[] { }, new object[] { new CodePrimitiveExpression(property.Browseable) }));
			attributeList.Add(new AttributeInfo(typeof(DesignerSerializationVisibilityAttribute), new string[] { }, new object[] { new CodeSnippetExpression(typeof(DesignerSerializationVisibility).Name + "." + property.DesignerSerializationVisibility.ToString()) }));

 			return attributeList.ToArray(); 
 		}
 
		private static bool ArePropertiesDifferent(CustomProperty property, CustomProperty oldProperty) 
 		{
			if (property.Name == oldProperty.Name && 
				property.Type == oldProperty.Type &&
				property.Browseable == oldProperty.Browseable &&
 				property.Category == oldProperty.Category &&
				property.Description == oldProperty.Description && 
 				property.DesignerSerializationVisibility == oldProperty.DesignerSerializationVisibility &&
 				property.Hidden == oldProperty.Hidden && 
				property.UITypeEditor == oldProperty.UITypeEditor) 
 			{
				return false; 
			}

			return true;
 		} 
		#endregion
 	} 
    #endregion 

 	#region Class BaseClassTypeFilterProvider 
	internal sealed class BaseClassTypeFilterProvider : ITypeFilterProvider
    {
 		private IServiceProvider serviceProvider;
 
        public BaseClassTypeFilterProvider(IServiceProvider serviceProvider)
        { 
			this.serviceProvider = serviceProvider; 
        }
 
        #region ITypeFilterProvider Members
        bool ITypeFilterProvider.CanFilterType(Type type, bool throwOnError)
        {
			bool filterType = false; 
			if (TypeProvider.IsAssignable(typeof(Activity), type) && type.IsPublic && !type.IsSealed && !type.IsAbstract && !(type is DesignTimeType))
 			{ 
                filterType = true; 
			}
 
 			return filterType;
        }

        string ITypeFilterProvider.FilterDescription 
        {
            get 
            { 
                return SR.GetString(SR.CustomActivityBaseClassTypeFilterProviderDesc);
            } 
        }
        #endregion
    }
    #endregion 

    #region CustomProperties 
    internal sealed class CustomProperty 
    {
        public string oldPropertyName; 
        public string oldPropertyType;
        private string name;
        private string type;
        private string category; 
        private string description;
        private DesignerSerializationVisibility designerSerializationVisibility = DesignerSerializationVisibility.Visible; 
        // NOTE: we don't write the ValidationOption attribute anymore (WinOE Bug 17398). We have removed our property creation 
        // dialog in beta1.  Now this code is only used for property promotion.  If the promoted property is a meta property,
        // it can not be bindable so no promotion is not allowed.  If the property is an instance property, this attribute is ignored. 
        // There is no reason for writing out this attribute anymore.We just remove it from property promotion all together.
        // NOTE II: for the same reason that this code is only used for promotion, we don't write out meta properties anymore.
        // We had customized the CodeDomSerializer.Deserialize to recognize meta properties by inspecting the field init expression,
        // which is no long needed.  If we were to bring this functionality back in the future, sample code can be found 
        // from the file history in Source Depot.
        private bool isEvent = false; 
        private bool browseable = true; 
        private bool hidden = false;
        private string uiTypeEditor; 
        private IServiceProvider serviceProvider = null;
        private bool generateDependencyProperty = true;

        public CustomProperty(IServiceProvider serviceProvider) 
        {
            this.serviceProvider = serviceProvider; 
        } 

        public string Name 
        {
            get
            {
                return this.name; 
            }
            set 
            { 
                this.name = value;
            } 
        }

        public string Type
        { 
            get
            { 
                return this.type; 
            }
            set 
            {
                this.type = value;
            }
        } 

        public string Description 
        { 
            get
            { 
                return this.description;
            }
            set
            { 
                this.description = value;
            } 
        } 

        public string Category 
        {
            get
            {
                return this.category; 
            }
            set 
            { 
                this.category = value;
            } 
        }

        public bool Browseable
        { 
            get
            { 
                return this.browseable; 
            }
            set 
            {
                this.browseable = value;
            }
        } 

        public DesignerSerializationVisibility DesignerSerializationVisibility 
        { 
            get
            { 
                return this.designerSerializationVisibility;
            }
            set
            { 
                this.designerSerializationVisibility = value;
            } 
        } 

        public string UITypeEditor 
        {
            get
            {
                return this.uiTypeEditor; 
            }
            set 
            { 
                string typeName = value;
 
                // Try to make sure the type is specified witht he fullName;
                if (this.serviceProvider != null)
                {
                    ITypeProvider typeProvider = this.serviceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider; 
                    if (typeProvider == null)
                        throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName)); 
 
                    Type type = typeProvider.GetType(typeName);
                    if (type != null) 
                        typeName = type.FullName;
                }

                this.uiTypeEditor = typeName; 
            }
        } 
 
        public bool IsEvent
        { 
            get
            {
                return this.isEvent;
            } 
            set
            { 
                this.isEvent = value; 
            }
        } 

        public bool Hidden
        {
            get 
            {
                return this.hidden; 
            } 
            set
            { 
                this.hidden = value;
            }
        }
 
        public bool GenerateDependencyProperty
        { 
            get 
            {
                return this.generateDependencyProperty; 
            }

            set
            { 
                this.generateDependencyProperty = value;
            } 
        } 

        #region Private Helpers 
        public static CustomProperty CreateCustomProperty(IServiceProvider serviceProvider, string customPropertyName, PropertyDescriptor propertyDescriptor, object propertyOwner)
        {
            CustomProperty newCustomProperty = new CustomProperty(serviceProvider);
            newCustomProperty.Name = customPropertyName; 
            if (TypeProvider.IsAssignable(typeof(ActivityBind), propertyDescriptor.PropertyType))
            { 
                Type baseType = PropertyDescriptorUtils.GetBaseType(propertyDescriptor, propertyOwner, serviceProvider); 
                if (baseType == null)
                    throw new InvalidOperationException(SR.GetString(SR.Error_CantDeterminePropertyBaseType, propertyDescriptor.Name)); 
                newCustomProperty.Type = baseType.FullName;
            }
            else
            { 
                newCustomProperty.Type = propertyDescriptor.PropertyType.FullName;
            } 
 
            if (propertyDescriptor is ActivityBindPropertyDescriptor)
            { 
                DependencyProperty dependencyProperty = DependencyProperty.FromName(propertyDescriptor.Name, propertyDescriptor.ComponentType);
                newCustomProperty.IsEvent = (dependencyProperty != null && dependencyProperty.IsEvent);
            }
 
            newCustomProperty.Category = propertyDescriptor.Category;
            return newCustomProperty; 
        } 
        #endregion
    } 
    #endregion

}

// 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