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 }