PropertyDescriptors.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

                            namespace System.Workflow.ComponentModel.Design 
{
 	#region Imports

	using System; 
	using System.IO;
	using System.ComponentModel; 
 	using System.ComponentModel.Design; 
	using System.Collections;
 	using System.Collections.Generic; 
 	using System.Reflection;
	using System.CodeDom;
    using System.Windows.Forms;
    using System.Windows.Forms.Design; 
 	using System.Workflow.ComponentModel.Compiler;
	using System.Workflow.ComponentModel.Serialization; 
	 
	using System.Drawing.Design;
 	using System.Collections.Specialized; 
	using System.Diagnostics;
    using System.Globalization;

 	#endregion 

 	#region Class IDPropertyDescriptor 
	internal sealed class IDPropertyDescriptor : DynamicPropertyDescriptor 
 	{
		internal IDPropertyDescriptor(IServiceProvider serviceProvider, PropertyDescriptor actualPropDesc) 
            :base(serviceProvider, actualPropDesc)
		{
		}
 
        public override bool CanResetValue(object component)
        { 
            return false; 
        }
 
 		public override void SetValue(object component, object value)
		{
 			Activity activity = component as Activity;
 			if (activity != null) 
			{
 				ISite site = PropertyDescriptorUtils.GetSite(ServiceProvider, component); 
				if(site == null) 
					throw new Exception(SR.GetString(SR.General_MissingService, typeof(ISite).FullName));
 
				IIdentifierCreationService identifierCreationService = site.GetService(typeof(IIdentifierCreationService)) as IIdentifierCreationService;
 				if (identifierCreationService == null)
					throw new Exception(SR.GetString(SR.General_MissingService, typeof(IIdentifierCreationService).FullName));
 
                string newID = value as string;
                identifierCreationService.ValidateIdentifier(activity, newID); 
 
                DesignerHelpers.UpdateSiteName(activity, newID);
                base.SetValue(component, value); 
            }
        }
 	}
 	#endregion 

    #region Class NamePropertyDescriptor 
    internal sealed class NamePropertyDescriptor : DynamicPropertyDescriptor 
    {
        internal NamePropertyDescriptor(IServiceProvider serviceProvider, PropertyDescriptor actualPropDesc) 
            : base(serviceProvider, actualPropDesc)
        {
        }
 
        public override string Category
        { 
            get 
            {
                return SR.GetString(SR.Activity); 
            }
        }

        public override string Description 
        {
            get 
            { 
                return SR.GetString(SR.RootActivityNameDesc);
            } 
        }

        public override void SetValue(object component, object value)
        { 
            Activity activity = component as Activity;
            if (activity != null) 
            { 
                // validate the identifier
                IIdentifierCreationService identifierCreationService = activity.Site.GetService(typeof(IIdentifierCreationService)) as IIdentifierCreationService; 
                if (identifierCreationService == null)
                    throw new Exception(SR.GetString(SR.General_MissingService, typeof(IIdentifierCreationService).FullName));

                string name = value as string; 
                identifierCreationService.ValidateIdentifier(activity, name);
 
                bool isVB = (CompilerHelpers.GetSupportedLanguage(activity.Site) == SupportedLanguages.VB); 
                Type designedType = Helpers.GetDataSourceClass(Helpers.GetRootActivity(activity), activity.Site);
                if (designedType != null) 
                {
                    MemberInfo matchingMember = ActivityBindPropertyDescriptor.FindMatchingMember(name, designedType, isVB);
                    if (matchingMember != null)
                        throw new ArgumentException(SR.GetString(SR.Error_ActivityNameExist, name)); 
                }
                IMemberCreationService memberCreationService = activity.Site.GetService(typeof(IMemberCreationService)) as IMemberCreationService; 
                if (memberCreationService == null) 
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IMemberCreationService).FullName));
 
                IDesignerHost host = activity.Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (host == null)
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
 
                // We need to update the activityType's name before trying to update the type because
                // updating the type causes a flush, which access the custom activity's properties, and 
                // doing so requires the new type name 
                string newClassName = name;
                int indexOfDot = host.RootComponentClassName.LastIndexOf('.'); 
                if (indexOfDot > 0)
                    newClassName = host.RootComponentClassName.Substring(0, indexOfDot + 1) + name;

                // IMPORTANT: You must update the class name in code before renaming the site, since 
                // VS's OnComponentRename updates the RootComponentClassName, so the flush code called
                // in our OnComponentRename tries to access the new class for information. 
                memberCreationService.UpdateTypeName(((Activity)host.RootComponent).GetValue(WorkflowMarkupSerializer.XClassProperty) as string, newClassName); 

                //((Activity)host.RootComponent).Name = name; 
                ((Activity)host.RootComponent).SetValue(WorkflowMarkupSerializer.XClassProperty, newClassName);
				base.SetValue(component, value);

 				// Update the site name so the component name shows up correctly in the designer 
				DesignerHelpers.UpdateSiteName((Activity)host.RootComponent, name);
            } 
        } 

        public override bool CanResetValue(object component) 
        {
            return false;
        }
    } 
    #endregion
 
	#region Class PropertyDescriptorUtils 
    internal static class PropertyDescriptorFilter
    { 
        internal static PropertyDescriptorCollection FilterProperties(IServiceProvider serviceProvider, object propertyOwner, PropertyDescriptorCollection props)
        {
            Hashtable properties = new Hashtable();
            foreach (PropertyDescriptor prop in props) 
            {
                if (!properties.ContainsKey(prop.Name)) 
                    properties.Add(prop.Name, prop); 
            }
 
            FilterProperties(serviceProvider, propertyOwner, properties);

            PropertyDescriptor[] returnProps = new PropertyDescriptor[properties.Count];
            properties.Values.CopyTo(returnProps, 0); 
            return new PropertyDescriptorCollection(returnProps);
        } 
 
        internal static void FilterProperties(IServiceProvider serviceProvider, object propertyOwner, IDictionary props)
        { 
            InternalFilterProperties(serviceProvider, propertyOwner, props);

            if (propertyOwner != null)
            { 
                foreach (PropertyDescriptor property in GetPropertiesForEvents(serviceProvider, propertyOwner))
                { 
                    if (!props.Contains(property.Name)) 
                        props.Add(property.Name, property);
                } 
            }
        }

        private static void InternalFilterProperties(IServiceProvider serviceProvider, object propertyOwner, IDictionary properties) 
        {
            // change property descriptors 
            Hashtable newProperties = new Hashtable(); 
            foreach (object key in properties.Keys)
            { 
                PropertyDescriptor propDesc = properties[key] as PropertyDescriptor;
				if (string.Equals(propDesc.Name, "Name", StringComparison.Ordinal) && typeof(Activity).IsAssignableFrom(propDesc.ComponentType))
                {
                    //Activity id 
                    Activity activity = propertyOwner as Activity;
                    if (activity != null && activity == Helpers.GetRootActivity(activity)) 
                        newProperties[key] = new NamePropertyDescriptor(serviceProvider, propDesc); 
                    else
                        newProperties[key] = new IDPropertyDescriptor(serviceProvider, propDesc); 
                }
                else if (!(propDesc is ActivityBindPropertyDescriptor) && ActivityBindPropertyDescriptor.IsBindableProperty(propDesc))
                {
                    if (typeof(Type).IsAssignableFrom(propDesc.PropertyType) && !(propDesc is ParameterInfoBasedPropertyDescriptor)) 
                        propDesc = new TypePropertyDescriptor(serviceProvider, propDesc);
                    newProperties[key] = new ActivityBindPropertyDescriptor(serviceProvider, propDesc, propertyOwner); 
                } 
                else if (typeof(Type).IsAssignableFrom(propDesc.PropertyType))
                { 
                    newProperties[key] = new TypePropertyDescriptor(serviceProvider, propDesc);
                }
                else
                { 
                    newProperties[key] = new DynamicPropertyDescriptor(serviceProvider, propDesc);
                } 
            } 

            foreach (object key in newProperties.Keys) 
            {
                properties[key] = newProperties[key];
            }
        } 

        internal static PropertyDescriptorCollection GetPropertiesForEvents(IServiceProvider serviceProvider, object eventOwner) 
        { 
            //Now for each event we need to add properties
            List properties = new List(); 

            // Find out if there is a data context.
            IEventBindingService eventBindingService = serviceProvider.GetService(typeof(IEventBindingService)) as IEventBindingService;
            if (eventBindingService != null) 
            {
                foreach (EventDescriptor eventDesc in TypeDescriptor.GetEvents(eventOwner)) 
                { 
                    if (eventDesc.IsBrowsable)
                    { 
                        PropertyDescriptor propertyDescriptor = eventBindingService.GetEventProperty(eventDesc);
                        if (!(propertyDescriptor is ActivityBindPropertyDescriptor) && ActivityBindPropertyDescriptor.IsBindableProperty(propertyDescriptor))
                            properties.Add(new ActivityBindPropertyDescriptor(serviceProvider, propertyDescriptor, eventOwner));
                        else 
                            properties.Add(propertyDescriptor);
                    } 
                } 
            }
 
            return new PropertyDescriptorCollection(properties.ToArray());
        }
    }
    #endregion 

    #region ActivityBind PropertyBrowser Integration 
 
    #region Class ActivityBindPropertyDescriptor
    ///Please note that ActivityBindPropertyDescriptor is now changed so that it can support MetaProperty binds too. 
 	///Although this feature is not yet enabled. Please change code in the PropertyDescritorUtils.InternalFilterProperties to support it

    ///We need this property descriptor for following reason:
    ///When we are not in data context we support emission of events directly by using EventBindingService 
    ///When we do this the events dont get stored in the DependencyObject rather than we store them in userdata
    ///Only the event property descriptor knows how to get it back. 
    ///At the same time we also support Promotion of the events (ActivityBind) when using this the information gets 
    ///stored directly in the DependencyObject which we fetch from the ActivityBindPropertyDescriptor base class
 
    ///Whenever the code in this class is changed please run the following test cases
    ///1. In ActivityDesigner Drop Code and Promote Properties. (ExecuteCode should get promoted)
    ///2. In ActivityDesigner, change the promoted property to event handler (Event needs to be emitted with += syntax)
    ///3. In ActivityDesigner, Set the data context to true and try to generate the event for code. (Event should be emitted in DataContext) 
    ///4. In ActivityDesigner, make sure that when within data context the serialization works through the bind, when outside works through +=
    ///Try all of the above cases in WorkflowDesigner where root supports datacontext, roots that dont support data context 
    internal class ActivityBindPropertyDescriptor : DynamicPropertyDescriptor 
	{
        private object propertyOwner = null; 

        internal ActivityBindPropertyDescriptor(IServiceProvider serviceProvider, PropertyDescriptor realPropertyDescriptor, object propertyOwner)
            : base(serviceProvider, realPropertyDescriptor)
        { 
            this.propertyOwner = propertyOwner;
        } 
 
 		public override bool IsReadOnly
 		{ 
			get
 			{
                return RealPropertyDescriptor.IsReadOnly;
            } 
		}
 
		public override TypeConverter Converter 
		{
 			get 
			{
 				TypeConverter baseTypeConverter = base.Converter;
 				if (typeof(ActivityBindTypeConverter).IsAssignableFrom(baseTypeConverter.GetType()))
					return baseTypeConverter; 
 				else
					return new ActivityBindTypeConverter(); 
			} 
		}
 
        public override AttributeCollection Attributes
        {
            get
            { 
                List attributes = new List();
                foreach (Attribute attribute in base.Attributes) 
                    attributes.Add(attribute); 

                object uiTypeEditor = RealPropertyDescriptor.GetEditor(typeof(UITypeEditor)); 
                object value = (PropertyOwner != null) ? GetValue(PropertyOwner) : null;
                bool propertiesSupported = RealPropertyDescriptor.Converter.GetPropertiesSupported((PropertyOwner != null) ? new TypeDescriptorContext(ServiceProvider, RealPropertyDescriptor, PropertyOwner) : null);
                if (((uiTypeEditor == null && !propertiesSupported) || value is ActivityBind) && !IsReadOnly)
                    attributes.Add(new EditorAttribute(typeof(BindUITypeEditor), typeof(UITypeEditor))); 

                return new AttributeCollection(attributes.ToArray()); 
            } 
        }
 
        public override object GetEditor(Type editorBaseType)
        {
            //If the converter is simple type converter and there is a simple UITypeEditor
            object editor = base.GetEditor(editorBaseType); 
            if (editorBaseType == typeof(UITypeEditor) && !IsReadOnly)
            { 
                object value = (PropertyOwner != null) ? GetValue(PropertyOwner) : null; 
                bool propertiesSupported = RealPropertyDescriptor.Converter.GetPropertiesSupported((PropertyOwner != null) ? new TypeDescriptorContext(ServiceProvider, RealPropertyDescriptor, PropertyOwner) : null);
                if (value is ActivityBind || (editor == null && !propertiesSupported)) 
                    editor = new BindUITypeEditor();
            }
            return editor;
        } 

 		public override object GetValue(object component) 
		{ 
 			object value = null;
 
 			DependencyObject dependencyObj = component as DependencyObject;
			DependencyProperty dependencyProperty = DependencyProperty.FromName(Name, ComponentType);
 			if (dependencyObj != null && dependencyProperty != null)
			{ 
				if (dependencyObj.IsBindingSet(dependencyProperty))
					value = dependencyObj.GetBinding(dependencyProperty); 
 			} 

			//We have to also call base's getvalue as Bindings are stored in MetaProperties collection of DependencyObject but 
 			//actual values are stored in DependencyValueProperties
 			if (!(value is ActivityBind))
				value = base.GetValue(component);
 
 			return value;
		} 
 
		public override void SetValue(object component, object value)
		{ 
            object oldValue = GetValue(component);

            ActivityBind activityBind = value as ActivityBind;
 
            DependencyObject dependencyObj = component as DependencyObject;
            DependencyProperty dependencyProperty = DependencyProperty.FromName(Name, ComponentType); 
            if (dependencyObj != null && dependencyProperty != null && activityBind != null) 
 		    {
			    ComponentChangeDispatcher componentChangeDispatcher = new ComponentChangeDispatcher(ServiceProvider, dependencyObj, this); 
 			    try
 			    {
                    if (dependencyProperty.IsEvent && ServiceProvider != null)
                    { 
                        IEventBindingService eventBindingService = ServiceProvider.GetService(typeof(IEventBindingService)) as IEventBindingService;
                        if (eventBindingService != null) 
                        { 
                            EventDescriptor eventDescriptor = eventBindingService.GetEvent(RealPropertyDescriptor);
                            if (eventDescriptor != null) 
                                RealPropertyDescriptor.SetValue(component, null);
                        }
                    }
 
				    dependencyObj.SetBinding(dependencyProperty, activityBind);
 				    base.OnValueChanged(dependencyObj, EventArgs.Empty); 
			    } 
			    finally
			    { 
 				    componentChangeDispatcher.Dispose();
			    }
 		    }
            else 
            {
                if (dependencyObj != null && dependencyProperty != null && dependencyObj.IsBindingSet(dependencyProperty)) 
                { 
                    ComponentChangeDispatcher componentChangeDispatcher = new ComponentChangeDispatcher(ServiceProvider, dependencyObj, this);
                    try 
                    {
                        dependencyObj.RemoveProperty(dependencyProperty);
                        // Need to fire component changed event because this means we're clearing
                        // out a previously set Bind value.  If the new value matches the old value stored in the user data, 
                        // base.SetValue will do nothing but return.  When that happens, if we don't fire a change
                        // event here, we'll still have the activity bind in the code or xoml file. 
                        base.OnValueChanged(dependencyObj, EventArgs.Empty); 
                    }
                    finally 
                    {
                        componentChangeDispatcher.Dispose();
                    }
                } 

 				base.SetValue(component, value); 
            } 

            //Following code is for making sure that when we change the value from activity bind to actual value 
            //and from actual value to activity bind; we need to change the UITypeEditor associated with property
            //from data binding editor to the editor specified by the user
            if (oldValue != value &&
                ((oldValue is ActivityBind && !(value is ActivityBind)) || 
                 (!(oldValue is ActivityBind) && value is ActivityBind)))
            { 
                TypeDescriptor.Refresh(component); 
            }
        } 

        #region Helpers
        internal object PropertyOwner
        { 
            get
            { 
                return this.propertyOwner; 
            }
        } 
        #endregion

        #region Static Helpers
        internal static IList GetBindableMembers(object obj, ITypeDescriptorContext context) 
        {
            List memberInfos = new List(); 
 
            IDesignerHost designerHost = context.GetService(typeof(IDesignerHost)) as IDesignerHost;
            Activity rootActivity = (designerHost != null) ? designerHost.RootComponent as Activity : null; 
            Type objectType = (obj == rootActivity) ? Helpers.GetDataSourceClass(rootActivity, context) : obj.GetType();

            Type memberType = PropertyDescriptorUtils.GetBaseType(context.PropertyDescriptor, context.Instance, context);
 
            if (objectType != null && memberType != null)
            { 
                DependencyProperty dependencyProperty = DependencyProperty.FromName(context.PropertyDescriptor.Name, context.PropertyDescriptor.ComponentType); 
                bool includeEvents = (dependencyProperty != null && dependencyProperty.IsEvent);
 
                BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy;
                if (obj == rootActivity)
                    bindingFlags |= BindingFlags.NonPublic;
 
                foreach (MemberInfo memberInfo in objectType.GetMembers(bindingFlags))
                { 
                    //filter our methods with System.Diagnostics.DebuggerNonUserCodeAttribute 
                    object[] nonUserCodeAttributes = memberInfo.GetCustomAttributes(typeof(System.Diagnostics.DebuggerNonUserCodeAttribute), false);
                    if (nonUserCodeAttributes != null && nonUserCodeAttributes.Length > 0 && nonUserCodeAttributes[0] is System.Diagnostics.DebuggerNonUserCodeAttribute) 
                        continue;

                    object[] browsableAttributes = memberInfo.GetCustomAttributes(typeof(BrowsableAttribute), false);
                    if (browsableAttributes.Length > 0) 
                    {
                        bool browsable = false; 
 
                        BrowsableAttribute browsableAttribute = browsableAttributes[0] as BrowsableAttribute;
                        if (browsableAttribute != null) 
                        {
                            browsable = browsableAttribute.Browsable;
                        }
                        else 
                        {
                            try 
                            { 
                                AttributeInfoAttribute attributeInfoAttribute = browsableAttributes[0] as AttributeInfoAttribute;
                                if (attributeInfoAttribute != null && attributeInfoAttribute.AttributeInfo.ArgumentValues.Count > 0) 
									browsable = (bool)attributeInfoAttribute.AttributeInfo.GetArgumentValueAs(context, 0, typeof(bool));
                            }
                            catch
                            { 
                            }
                        } 
 
                        if (!browsable)
                            continue; 
                    }

                    if (memberInfo.DeclaringType == typeof(System.Object) && (string.Equals(memberInfo.Name, "Equals", StringComparison.Ordinal) || string.Equals(memberInfo.Name, "ReferenceEquals", StringComparison.Ordinal)))
                        continue; 

                    bool addMember = false; 
                    bool isProtectedOrPublicMember = false; 
                    bool isInternalMember = false;
                    if (includeEvents && memberInfo is EventInfo) 
                    {
                        EventInfo eventInfo = memberInfo as EventInfo;

                        MethodInfo addAccessor = eventInfo.GetAddMethod(); 
                        MethodInfo removeAccessor = eventInfo.GetRemoveMethod();
 
                        isProtectedOrPublicMember = ((addAccessor != null && addAccessor.IsFamily) || (removeAccessor != null && removeAccessor.IsFamily) || 
                                                    (addAccessor != null && addAccessor.IsPublic) || (removeAccessor != null && removeAccessor.IsPublic));
                        isInternalMember = ((addAccessor != null && addAccessor.IsAssembly) || (removeAccessor != null && removeAccessor.IsAssembly)); 

                        addMember = TypeProvider.IsAssignable(memberType, eventInfo.EventHandlerType);
                    }
                    else if (memberInfo is FieldInfo) 
                    {
                        FieldInfo fieldInfo = memberInfo as FieldInfo; 
                        isProtectedOrPublicMember = (fieldInfo.IsFamily || fieldInfo.IsPublic); 
                        isInternalMember = fieldInfo.IsAssembly;
                        addMember = TypeProvider.IsAssignable(memberType, fieldInfo.FieldType); 
                    }
                    else if (memberInfo is PropertyInfo)
                    {
                        PropertyInfo propertyInfo = memberInfo as PropertyInfo; 

                        MethodInfo getAccessor = propertyInfo.GetGetMethod(); 
                        MethodInfo setAccessor = propertyInfo.GetSetMethod(); 

                        isProtectedOrPublicMember = ((getAccessor != null && getAccessor.IsFamily) || (setAccessor != null && setAccessor.IsFamily) || 
                                                    (getAccessor != null && getAccessor.IsPublic) || (setAccessor != null && setAccessor.IsPublic));
                        isInternalMember = ((getAccessor != null && getAccessor.IsAssembly) || (setAccessor != null && setAccessor.IsAssembly));
                        addMember = (getAccessor != null && TypeProvider.IsAssignable(memberType, propertyInfo.PropertyType));
                    } 

                    //We only want to allow binding to protected, public and internal members of baseType 
                    if (memberInfo.DeclaringType != objectType && !isProtectedOrPublicMember && !(memberInfo.DeclaringType.Assembly == null && isInternalMember)) 
                        addMember = false;
 
                    if (addMember)
                        memberInfos.Add(memberInfo);
                }
            } 

            return memberInfos.AsReadOnly(); 
        } 

        internal static bool CreateField(ITypeDescriptorContext context, ActivityBind activityBind, bool throwOnError) 
        {
            //Check if the activity is root activity and has valid design time type
            if (!String.IsNullOrEmpty(activityBind.Path))
            { 
                Type boundType = PropertyDescriptorUtils.GetBaseType(context.PropertyDescriptor, context.Instance, context);
                Activity activity = PropertyDescriptorUtils.GetComponent(context) as Activity; 
                if (activity != null && boundType != null) 
                {
                    activity = Helpers.ParseActivityForBind(activity, activityBind.Name); 
                    if (activity == Helpers.GetRootActivity(activity))
                    {
                        bool isVB = (CompilerHelpers.GetSupportedLanguage(context) == SupportedLanguages.VB);
                        Type designedType = Helpers.GetDataSourceClass(activity, context); 
                        if (designedType != null)
                        { 
 							//field path could be nested too. 
							//need to find field only with the name up to the first dot (CimplexTypeField in the example below)
							//and the right type (that would be tricky if the field doesnt exist yet) 
							//example: CimplexTypeField.myIDictionary_int_string[10].someOtherGood2

 							string fieldName = activityBind.Path;
							int indexOfDot = fieldName.IndexOfAny(new char[] { '.', '/', '[' }); 
 							if (indexOfDot != -1)
 								fieldName = fieldName.Substring(0, indexOfDot);//path is a nested field access 
 
                            MemberInfo matchingMember = ActivityBindPropertyDescriptor.FindMatchingMember(fieldName, designedType, isVB);
                            if (matchingMember != null) 
                            {
                                Type memberType = null;
                                bool isPrivate = false;
                                if (matchingMember is FieldInfo) 
                                {
                                    isPrivate = ((FieldInfo)matchingMember).IsPrivate; 
                                    memberType = ((FieldInfo)matchingMember).FieldType; 
                                }
                                else if (matchingMember is PropertyInfo) 
                                {
                                    MethodInfo getMethod = ((PropertyInfo)matchingMember).GetGetMethod();
                                    MethodInfo setMethod = ((PropertyInfo)matchingMember).GetSetMethod();
                                    isPrivate = ((getMethod != null && getMethod.IsPrivate) || (setMethod != null && setMethod.IsPrivate)); 
                                }
                                else if (matchingMember is MethodInfo) 
                                { 
                                    isPrivate = ((MethodInfo)matchingMember).IsPrivate;
                                } 

                                if (indexOfDot != -1)
                                {//need to find the type of the member the path references (and if the path is valid at all)
                                    PathWalker pathWalker = new PathWalker(); 
                                    PathMemberInfoEventArgs finalEventArgs = null;
                                    pathWalker.MemberFound += delegate(object sender, PathMemberInfoEventArgs eventArgs) 
                                    { finalEventArgs = eventArgs; }; 

                                    if (pathWalker.TryWalkPropertyPath(designedType, activityBind.Path)) 
                                    {
                                        //successfully walked the entire path
                                        memberType = BindHelpers.GetMemberType(finalEventArgs.MemberInfo);
                                    } 
                                    else
                                    { 
                                        //the path is invalid 
                                        if (throwOnError)
                                            throw new InvalidOperationException(SR.GetString(SR.Error_MemberWithSameNameExists, activityBind.Path, designedType.FullName)); 

                                        return false;
                                    }
                                } 

                                if ((matchingMember.DeclaringType == designedType || !isPrivate) && 
                                    matchingMember is FieldInfo && 
                                    TypeProvider.IsAssignable(boundType, memberType))
                                { 
                                    return true;
                                }
                                else
                                { 
                                    if (throwOnError)
                                        throw new InvalidOperationException(SR.GetString(SR.Error_MemberWithSameNameExists, activityBind.Path, designedType.FullName)); 
                                    return false; 
                                }
                            } 
                            else
                            {
                                // Find out if the name conflicts with an existing activity that has not be flushed in to the
                                // code beside.  An activity bind can bind to this field only if the type of the property 
                                // is the assignable from the activity type.
                                Activity matchingActivity = null; 
                                if (string.Compare(activity.Name, fieldName, isVB ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) == 0) 
                                    matchingActivity = activity;
                                else if (activity is CompositeActivity) 
                                {
                                    if (activity is CompositeActivity)
                                    {
                                        foreach (Activity existingActivity in Helpers.GetAllNestedActivities(activity as CompositeActivity)) 
                                        {
                                            if (string.Compare(existingActivity.Name, fieldName, isVB ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) == 0) 
                                                matchingActivity = existingActivity; 
                                        }
                                    } 
                                }

                                if (matchingActivity != null)
                                { 
                                    if (TypeProvider.IsAssignable(boundType, matchingActivity.GetType()))
                                        return true; 
                                    else 
                                    {
                                        if (throwOnError) 
                                           throw new InvalidOperationException(SR.GetString(SR.Error_MemberWithSameNameExists, activityBind.Path, designedType.FullName));
                                        return false;
                                    }
                                } 
                            }
 
                            IMemberCreationService memberCreationService = context.GetService(typeof(IMemberCreationService)) as IMemberCreationService; 
                            if (memberCreationService == null)
                            { 
                                if (throwOnError)
                                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(IMemberCreationService).FullName));
                            }
                            else 
                            {
								IDesignerHost designerHost = context.GetService(typeof(IDesignerHost)) as IDesignerHost; 
 								if (designerHost == null) 
								{
									if (throwOnError) 
										throw new InvalidOperationException(SR.GetString("General_MissingService", typeof(IDesignerHost).FullName));
 								}
								else
 								{ 
 									memberCreationService.CreateField(designerHost.RootComponentClassName, activityBind.Path, boundType, null, MemberAttributes.Public, null, false);
									return true; 
 								} 
                            }
                        } 
                    }
                }
                else
                { 
                    if (activity == null && throwOnError)
                        throw new InvalidOperationException(SR.GetString(SR.Error_InvalidActivityIdentifier, activityBind.Name)); 
 
                    if (boundType == null && throwOnError)
                        throw new InvalidOperationException(SR.GetString(SR.Error_PropertyTypeNotDefined, context.PropertyDescriptor.Name, typeof(ActivityBind).Name, typeof(IDynamicPropertyTypeProvider).Name)); 
                }
            }

            return false; 
        }
 
        internal static bool IsBindableProperty(PropertyDescriptor propertyDescriptor) 
        {
            //The property type itself is ActivityBind; we dont support such cases very well in componentmodel 
            //but still we need to handle such cases as a fallback in ui
            if (propertyDescriptor.PropertyType == typeof(ActivityBind))
                return true;
 
            //We check this condition so that we will make sure that ActivityBind UI infrastructure
            //kicks into action in cases of parameter properties. User might sometimes do this on their properties 
            //but in such cases they need to write their custom property descriptors just as we have written 
            //ParameterInfoBasedPropertyDescriptor
            if (propertyDescriptor.Converter is ActivityBindTypeConverter) 
                return true;

            //For all the other cases
            DependencyProperty dependencyProperty = DependencyProperty.FromName(propertyDescriptor.Name, propertyDescriptor.ComponentType); 
            if (typeof(DependencyObject).IsAssignableFrom(propertyDescriptor.ComponentType) && dependencyProperty != null && !dependencyProperty.DefaultMetadata.IsMetaProperty)
                return true; 
 
            return false;
        } 

        internal static MemberInfo FindMatchingMember(string name, Type ownerType, bool ignoreCase)
        {
            MemberInfo matchingMember = null; 
            foreach (MemberInfo memberInfo in ownerType.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
            { 
                if (memberInfo.Name.Equals(name, ((ignoreCase) ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal))) 
                {
                    matchingMember = memberInfo; 
                    break;
                }
            }
            return matchingMember; 
        }
        #endregion 
    } 
	#endregion
 
    #region Class ActivityBindNamePropertyDescriptor
    internal sealed class ActivityBindNamePropertyDescriptor : DynamicPropertyDescriptor
    {
        private ITypeDescriptorContext context; 

        public ActivityBindNamePropertyDescriptor(ITypeDescriptorContext context, PropertyDescriptor realPropertyDescriptor) 
            : base(context, realPropertyDescriptor) 
        {
            this.context = context; 
        }

        public override object GetValue(object component)
        { 
            object value = base.GetValue(component);
            string id = value as string; 
            if (!String.IsNullOrEmpty(id)) 
            {
                Activity activity = PropertyDescriptorUtils.GetComponent(this.context) as Activity; 
                activity = (activity != null) ? Helpers.ParseActivityForBind(activity, id) : null;
                value = (activity != null) ? activity.QualifiedName : id;
            }
 
            return value;
        } 
 
        public override void SetValue(object component, object value)
        { 
            string id = value as string;
            if (String.IsNullOrEmpty(id))
                throw new InvalidOperationException(SR.GetString(SR.Error_ActivityIdentifierCanNotBeEmpty));
 
            Activity activity = PropertyDescriptorUtils.GetComponent(this.context) as Activity;
            if (activity != null) 
            { 
                if (Helpers.ParseActivityForBind(activity, id) == null)
                    throw new InvalidOperationException(SR.GetString(SR.Error_InvalidActivityIdentifier, id)); 
            }

            base.SetValue(component, value);
        } 
    }
    #endregion 
 
    #region Class ActivityBindPathPropertyDescriptor
    internal sealed class ActivityBindPathPropertyDescriptor : DynamicPropertyDescriptor 
	{
        private ITypeDescriptorContext context;

        public ActivityBindPathPropertyDescriptor(ITypeDescriptorContext context, PropertyDescriptor realPropertyDescriptor) 
            : base(context, realPropertyDescriptor)
		{ 
            this.context = context; 
 		}
 
        internal ITypeDescriptorContext OuterPropertyContext
        {
            get
            { 
                return this.context;
            } 
        } 
	}
 	#endregion 

    #endregion

    #region ReadOnly Properties Integration 

    #region Class ReadonlyTypeDescriptorProvider 
    internal sealed class ReadonlyTypeDescriptonProvider : TypeDescriptionProvider 
    {
        internal ReadonlyTypeDescriptonProvider(TypeDescriptionProvider realProvider) 
            : base(realProvider)
        {
        }
 
        public override ICustomTypeDescriptor GetTypeDescriptor(Type type, object instance)
        { 
            ICustomTypeDescriptor realTypeDescriptor = base.GetTypeDescriptor(type, instance); 
            ICustomTypeDescriptor readonlyTypeDescriptor = new ReadonlyTypeDescriptor(realTypeDescriptor);
            return readonlyTypeDescriptor; 
        }
    }
    #endregion
 
    #region Class ReadonlyTypeDescriptor
    internal sealed class ReadonlyTypeDescriptor : CustomTypeDescriptor 
    { 
        internal ReadonlyTypeDescriptor(ICustomTypeDescriptor realTypeDescriptor)
            : base(realTypeDescriptor) 
        {
        }

        public override AttributeCollection GetAttributes() 
        {
            ArrayList collection = new ArrayList(); 
            foreach (Attribute attribute in base.GetAttributes()) 
            {
                //should not have any editor attribute and only one readonly attribute 
                if (!(attribute is EditorAttribute || attribute is ReadOnlyAttribute))
                    collection.Add(attribute);
            }
            collection.Add(new ReadOnlyAttribute(true)); 
            AttributeCollection newCollection = new AttributeCollection((Attribute[])collection.ToArray(typeof(Attribute)));
            return newCollection; 
        } 

        public override PropertyDescriptorCollection GetProperties() 
        {
            PropertyDescriptorCollection properties = base.GetProperties();

            ArrayList readonlyProperties = new ArrayList(); 
            foreach (PropertyDescriptor property in properties)
            { 
                BrowsableAttribute browsable = property.Attributes[typeof(BrowsableAttribute)] as BrowsableAttribute; 
                if (browsable != null && browsable.Browsable && !(property is ReadonlyPropertyDescriptor))
                    readonlyProperties.Add(new ReadonlyPropertyDescriptor(property)); 
                else
                    readonlyProperties.Add(property);
            }
 
            return new PropertyDescriptorCollection((PropertyDescriptor[])readonlyProperties.ToArray(typeof(PropertyDescriptor)));
        } 
 
        public override EventDescriptorCollection GetEvents(Attribute[] attributes)
        { 
            EventDescriptorCollection events = base.GetEvents(attributes);

            ArrayList readonlyEvents = new ArrayList();
            foreach (EventDescriptor e in events) 
            {
                BrowsableAttribute browsable = e.Attributes[typeof(BrowsableAttribute)] as BrowsableAttribute; 
                if (browsable != null && browsable.Browsable) 
                    readonlyEvents.Add(new ReadonlyEventDescriptor(e));
                else 
                    readonlyEvents.Add(e);
            }

            return new EventDescriptorCollection((EventDescriptor[])readonlyEvents.ToArray(typeof(EventDescriptor))); 
        }
    } 
    #endregion 

    #region Class ReadonlyPropertyDescriptor 
 	internal sealed class ReadonlyPropertyDescriptor : PropertyDescriptor
	{
 		private PropertyDescriptor realPropertyDescriptor;
 
		internal ReadonlyPropertyDescriptor(PropertyDescriptor descriptor)
			: base(descriptor, null) 
		{ 
 			this.realPropertyDescriptor = descriptor;
		} 

 		public override string Category
 		{
			get 
 			{
				return this.realPropertyDescriptor.Category; 
			} 
		}
 		public override AttributeCollection Attributes 
		{
 			get
 			{
				ArrayList collection = new ArrayList(); 
 				foreach (Attribute attribute in this.realPropertyDescriptor.Attributes)
				{ 
					//should not have any editor attribute and only one readonly attribute 
					if (!(attribute is EditorAttribute || attribute is ReadOnlyAttribute))
 						collection.Add(attribute); 
				}
 				collection.Add(new ReadOnlyAttribute(true));
 				AttributeCollection newCollection = new AttributeCollection((Attribute[])collection.ToArray(typeof(Attribute)));
				return newCollection; 
 			}
		} 
		public override TypeConverter Converter 
		{
 			get 
			{
 				return this.realPropertyDescriptor.Converter;
 			}
		} 
 		public override string Description
		{ 
			get 
			{
 				return this.realPropertyDescriptor.Description; 
			}
 		}
 		public override Type ComponentType
		{ 
 			get
			{ 
				return this.realPropertyDescriptor.ComponentType; 
			}
 		} 
		public override Type PropertyType
 		{
 			get
			{ 
 				return this.realPropertyDescriptor.PropertyType;
			} 
		} 
		public override bool IsReadOnly
 		{ 
			get
 			{
 				return true;
			} 
 		}
		public override void ResetValue(object component) 
		{ 
			this.realPropertyDescriptor.ResetValue(component);
 		} 
		public override bool CanResetValue(object component)
 		{
 			return false;
		} 
 		public override bool ShouldSerializeValue(object component)
		{ 
			return this.realPropertyDescriptor.ShouldSerializeValue(component); 
		}
 		public override object GetValue(object component) 
		{
 			return this.realPropertyDescriptor.GetValue(component);
 		}
		public override void SetValue(object component, object value) 
 		{
			//This is readonly property descriptor 
			Debug.Assert(false, "SetValue should not be called on readonly property!"); 
		}
 	} 
	#endregion

    #region Class ReadonlyEventDescriptor
    internal sealed class ReadonlyEventDescriptor : EventDescriptor 
    {
        private EventDescriptor realEventDescriptor; 
 
        internal ReadonlyEventDescriptor(EventDescriptor e)
            : base(e, null) 
        {
            this.realEventDescriptor = e;
        }
 
        public override string Category
        { 
            get 
            {
                return this.realEventDescriptor.Category; 
            }
        }
        public override AttributeCollection Attributes
        { 
            get
            { 
                ArrayList collection = new ArrayList(); 
                foreach (Attribute attribute in this.realEventDescriptor.Attributes)
                { 
                    //should not have any editor attribute and only one readonly attribute
                    if (!(attribute is EditorAttribute || attribute is ReadOnlyAttribute))
                        collection.Add(attribute);
                } 
                collection.Add(new ReadOnlyAttribute(true));
                AttributeCollection newCollection = new AttributeCollection((Attribute[])collection.ToArray(typeof(Attribute))); 
                return newCollection; 
            }
        } 
        public override string Description
        {
            get
            { 
                return this.realEventDescriptor.Description;
            } 
        } 
        public override Type ComponentType
        { 
            get
            {
                return this.realEventDescriptor.ComponentType;
            } 
        }
        public override Type EventType 
        { 
            get
            { 
                return this.realEventDescriptor.EventType;
            }
        }
        public override bool IsMulticast 
        {
            get 
            { 
                return this.realEventDescriptor.IsMulticast;
            } 
        }

        public override void AddEventHandler(object component, Delegate value)
        { 
            //This is readonly event descriptor
        } 
        public override void RemoveEventHandler(object component, Delegate value) 
        {
            //This is readonly event descriptor 
        }
    }
    #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