//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ #if DEBUG /* This class exists in debug only. It is a complete copy of the V1.0 TypeDescriptor object and is used to validate that the behavior of the V2.0 TypeDescriptor matches 1.0 behavior. */ namespace System.ComponentModel { using System.Diagnostics; using System; using System.ComponentModel.Design; using System.Collections; using Microsoft.Win32; using System.Security.Permissions; /// /// /// /// This class wraps an PropertyDescriptor with something that looks like a property. It /// allows you to treat extended properties the same as regular properties. /// /// [HostProtection(SharedState = true)] internal sealed class DebugExtendedPropertyDescriptor : PropertyDescriptor { private readonly DebugReflectPropertyDescriptor extenderInfo; // the extender property private readonly IExtenderProvider provider; // the guy providing it private TypeConverter converter; private object[] editors; private Type[] editorTypes; private int editorCount; /// /// Creates a new extended property info. Callers can then treat this as /// a standard property. /// public DebugExtendedPropertyDescriptor(DebugReflectPropertyDescriptor extenderInfo, Type receiverType, IExtenderProvider provider) : this(extenderInfo, receiverType, provider, null) { } /// /// Creates a new extended property info. Callers can then treat this as /// a standard property. /// public DebugExtendedPropertyDescriptor(DebugReflectPropertyDescriptor extenderInfo, Type receiverType, IExtenderProvider provider, Attribute[] attributes) : base(extenderInfo, attributes) { Debug.Assert(extenderInfo != null, "DebugExtendedPropertyDescriptor must have extenderInfo"); Debug.Assert(provider != null, "DebugExtendedPropertyDescriptor must have provider"); ArrayList attrList = new ArrayList(AttributeArray); attrList.Add(ExtenderProvidedPropertyAttribute.Create(extenderInfo, receiverType, provider)); if (extenderInfo.IsReadOnly) { attrList.Add(ReadOnlyAttribute.Yes); } Attribute[] temp = new Attribute[attrList.Count]; attrList.CopyTo(temp, 0); AttributeArray = temp; this.extenderInfo = extenderInfo; this.provider = provider; } public DebugExtendedPropertyDescriptor(PropertyDescriptor extender, Attribute[] attributes) : base(extender, attributes) { Debug.Assert(extender != null, "The original PropertyDescriptor must be non-null"); ExtenderProvidedPropertyAttribute attr = extender.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute; Debug.Assert(attr != null, "The original PropertyDescriptor does not have an ExtenderProvidedPropertyAttribute"); DebugReflectPropertyDescriptor reflectDesc = attr.ExtenderProperty as DebugReflectPropertyDescriptor; Debug.Assert(reflectDesc != null, "The original PropertyDescriptor has an invalid ExtenderProperty"); this.extenderInfo = reflectDesc; this.provider = attr.Provider; } /// /// Determines if the the component will allow its value to be reset. /// public override bool CanResetValue(object comp) { return extenderInfo.ExtenderCanResetValue(provider, comp); } /// /// Retrieves the type of the component this PropertyDescriptor is bound to. /// public override Type ComponentType { get { return extenderInfo.ComponentType; } } public override TypeConverter Converter { get { if (converter == null) { TypeConverterAttribute attr = (TypeConverterAttribute)Attributes[typeof(TypeConverterAttribute)]; if (attr.ConverterTypeName != null && attr.ConverterTypeName.Length > 0) { Type converterType = GetTypeFromName(attr.ConverterTypeName); if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType)) { converter = (TypeConverter)CreateInstance(converterType); } } if (converter == null) { converter = DebugTypeDescriptor.GetConverter(PropertyType); } } return converter; } } /// /// Determines if the property can be written to. /// public override bool IsReadOnly { get { return Attributes[typeof(ReadOnlyAttribute)].Equals(ReadOnlyAttribute.Yes); } } /// /// Retrieves the data type of the property. /// public override Type PropertyType { get { return extenderInfo.ExtenderGetType(provider); } } /// /// Retrieves the display name of the property. This is the name that will /// be displayed in a properties window. This will be the same as the property /// name for most properties. /// public override string DisplayName { get { string name = Name; ISite site = GetSite(provider); if (site != null) { string providerName = site.Name; if (providerName != null && providerName.Length > 0) { name = SR.GetString(SR.MetaExtenderName, name, providerName); } } return name; } } /// /// Retrieves the properties /// public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter) { if (instance == null) { return DebugTypeDescriptor.GetProperties(PropertyType, filter); } else { return DebugTypeDescriptor.GetProperties(instance, filter); } } /// /// /// Gets an editor of the specified type. /// /// public override object GetEditor(Type editorBaseType) { object editor = null; // Check the editors we've already created for this type. // if (editorTypes != null) { for (int i = 0; i < editorCount; i++) { if (editorTypes[i] == editorBaseType) { return editors[i]; } } } // If one wasn't found, then we must go through the attributes. // if (editor == null) { for (int i = 0; i < Attributes.Count; i++) { if (!(Attributes[i] is EditorAttribute)) { continue; } EditorAttribute attr = (EditorAttribute)Attributes[i]; Type editorType = GetTypeFromName(attr.EditorBaseTypeName); if (editorBaseType == editorType) { Type type = GetTypeFromName(attr.EditorTypeName); if (type != null) { editor = CreateInstance(type); break; } } } // Now, if we failed to find it in our own attributes, go to the // component descriptor. // if (editor == null) { editor = DebugTypeDescriptor.GetEditor(PropertyType, editorBaseType); } // Now, another slot in our editor cache for next time // if (editorTypes == null) { editorTypes = new Type[5]; editors = new object[5]; } if (editorCount >= editorTypes.Length) { Type[] newTypes = new Type[editorTypes.Length * 2]; object[] newEditors = new object[editors.Length * 2]; Array.Copy(editorTypes, newTypes, editorTypes.Length); Array.Copy(editors, newEditors, editors.Length); editorTypes = newTypes; editors = newEditors; } editorTypes[editorCount] = editorBaseType; editors[editorCount++] = editor; } return editor; } /// /// Retrieves the value of the property for the given component. This will /// throw an exception if the component does not have this property. /// public override object GetValue(object comp) { return extenderInfo.ExtenderGetValue(provider, comp); } /// /// Resets the value of this property on comp to the default value. /// public override void ResetValue(object comp) { extenderInfo.ExtenderResetValue(provider, comp, this); } /// /// Sets the value of this property on the given component. /// public override void SetValue(object component, object value) { extenderInfo.ExtenderSetValue(provider, component, value, this); } /// /// Determines if this property should be persisted. A property is /// to be persisted if it is marked as persistable through a /// PersistableAttribute, and if the property contains something other /// than the default value. Note, however, that this method will /// return true for design time properties as well, so callers /// should also check to see if a property is design time only before /// persisting to runtime storage. /// public override bool ShouldSerializeValue(object comp) { return extenderInfo.ExtenderShouldSerializeValue(provider, comp); } } } #endif