Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / System / ComponentModel / DependencyPropertyDescriptor.cs / 1305600 / DependencyPropertyDescriptor.cs
using MS.Internal.ComponentModel; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Reflection; using System.Text; using System.Security; using System.Windows; #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace System.ComponentModel { ////// This is a wrapper property descriptor that offers a merged API of /// both CLR and DependencyProperty features. To use it, call its /// static FromProperty method passing a PropertyDescriptor. The /// API degrades gracefully if the property descriptor passed does /// not represent a dependency property. /// public sealed class DependencyPropertyDescriptor : PropertyDescriptor { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// Creates a new dependency property descriptor. A note on perf: We don't /// pass the property descriptor down as the default member descriptor here. Doing /// so gets the attributes off of the property descriptor, which can be costly if they /// haven't been accessed yet. Instead, we wait until someone needs to access our /// Attributes property and demand create the attributes at that time. /// private DependencyPropertyDescriptor(PropertyDescriptor property, string name, Type componentType, DependencyProperty dp, bool isAttached) : base(name, null) { Debug.Assert(property != null || !isAttached, "Demand-load of property descriptor is only supported for direct properties"); _property = property; _componentType = componentType; _dp = dp; _isAttached = isAttached; _metadata = _dp.GetMetadata(componentType); } #endregion Constructors //----------------------------------------------------- // // Public Methods // //----------------------------------------------------- #region Public Methods ////// Static method that returns a DependencyPropertyDescriptor from a PropertyDescriptor. /// public static DependencyPropertyDescriptor FromProperty(PropertyDescriptor property) { if (property == null) throw new ArgumentNullException("property"); DependencyPropertyDescriptor dpd; bool found; lock(_cache) { found = _cache.TryGetValue(property, out dpd); } if (found) { return dpd; } // Locate the dependency property. We do this a fast way // by searching for InternalPropertyDescriptor, and a slow // way, by looking for an attribute. The fast way works unless // someone has added another layer of metadata overrides to // TypeDescriptor. DependencyProperty dp = null; bool isAttached = false; DependencyObjectPropertyDescriptor idpd = property as DependencyObjectPropertyDescriptor; if (idpd != null) { dp = idpd.DependencyProperty; isAttached = idpd.IsAttached; } else { #pragma warning suppress 6506 // property is obviously not null DependencyPropertyAttribute dpa = property.Attributes[typeof(DependencyPropertyAttribute)] as DependencyPropertyAttribute; if (dpa != null) { dp = dpa.DependencyProperty; isAttached = dpa.IsAttached; } } if (dp != null) { dpd = new DependencyPropertyDescriptor(property, property.Name, property.ComponentType, dp, isAttached); lock(_cache) { _cache[property] = dpd; } } return dpd; } ////// Static method that returns a DependencyPropertyDescriptor from a DependencyProperty. The /// DependencyProperty may refer to either a direct or attached property. The targetType is the /// type of object to associate with the property: either the owner type for a direct property /// or the type of object to attach to for an attached property. /// internal static DependencyPropertyDescriptor FromProperty(DependencyProperty dependencyProperty, Type ownerType, Type targetType, bool ignorePropertyType) { if (dependencyProperty == null) throw new ArgumentNullException("dependencyProperty"); if (targetType == null) throw new ArgumentNullException("targetType"); // We have a different codepath here for attached and direct // properties. For direct properties, we route through Type // Descriptor because we need the underlying CLR property descriptor // to create our wrapped property. For attached properties, all we // need is the dp and the object type and we can create an attached // property descriptor based on that. We must special case attached // properties here because TypeDescriptor will only return attached // properties for instances, not types. DependencyPropertyDescriptor dpd = null; if (ownerType.GetProperty(dependencyProperty.Name) != null) { // For direct properties we don't want to get the property descriptor // yet because it is very expensive. Delay it until needed. lock (_ignorePropertyTypeCache) { _ignorePropertyTypeCache.TryGetValue(dependencyProperty, out dpd); } if (dpd == null) { // Create a new DPD based on the type information we have. It // will fill in the property descriptor by calling TypeDescriptor // when needed. dpd = new DependencyPropertyDescriptor(null, dependencyProperty.Name, targetType, dependencyProperty, false); lock (_ignorePropertyTypeCache) { _ignorePropertyTypeCache[dependencyProperty] = dpd; } } } else { if (ownerType.GetMethod("Get" + dependencyProperty.Name) == null && ownerType.GetMethod("Set" + dependencyProperty.Name) == null) { return null; } // If it isn't a direct property, we treat it as attached unless it is internal. // We should never release internal properties to the user PropertyDescriptor prop = DependencyObjectProvider.GetAttachedPropertyDescriptor(dependencyProperty, targetType); if (prop != null) { dpd = FromProperty(prop); } } return dpd; } ////// Static method that returns a DependencyPropertyDescriptor from a DependencyProperty. The /// DependencyProperty may refer to either a direct or attached property. The targetType is the /// type of object to associate with the property: either the owner type for a direct property /// or the type of object to attach to for an attached property. /// public static DependencyPropertyDescriptor FromProperty(DependencyProperty dependencyProperty, Type targetType) { if (dependencyProperty == null) throw new ArgumentNullException("dependencyProperty"); if (targetType == null) throw new ArgumentNullException("targetType"); // We have a different codepath here for attached and direct // properties. For direct properties, we route through Type // Descriptor because we need the underlying CLR property descriptor // to create our wrapped property. For attached properties, all we // need is the dp and the object type and we can create an attached // property descriptor based on that. We must special case attached // properties here because TypeDescriptor will only return attached // properties for instances, not types. DependencyPropertyDescriptor dpd = null; DependencyPropertyKind dpKind = DependencyObjectProvider.GetDependencyPropertyKind(dependencyProperty, targetType); if (dpKind.IsDirect) { // For direct properties we don't want to get the property descriptor // yet because it is very expensive. Delay it until needed. lock(_cache) { _cache.TryGetValue(dependencyProperty, out dpd); } if (dpd == null) { // Create a new DPD based on the type information we have. It // will fill in the property descriptor by calling TypeDescriptor // when needed. dpd = new DependencyPropertyDescriptor(null, dependencyProperty.Name, targetType, dependencyProperty, false); lock(_cache) { _cache[dependencyProperty] = dpd; } } } else if (!dpKind.IsInternal) { // If it isn't a direct property, we treat it as attached unless it is internal. // We should never release internal properties to the user PropertyDescriptor prop = DependencyObjectProvider.GetAttachedPropertyDescriptor(dependencyProperty, targetType); if (prop != null) { dpd = FromProperty(prop); } } return dpd; } ////// Static method that returns a DependencyPropertyDescriptor for a given property name. /// The name may refer to a direct or attached property. OwnerType is the type of /// object that owns the property definition. TargetType is the type of object you wish /// to set the property for. For direct properties, they are the same type. For attached /// properties they usually differ. /// public static DependencyPropertyDescriptor FromName(string name, Type ownerType, Type targetType) { if (name == null) throw new ArgumentNullException("name"); if (ownerType == null) throw new ArgumentNullException("ownerType"); if (targetType == null) throw new ArgumentNullException("targetType"); DependencyProperty dp = DependencyProperty.FromName(name, ownerType); if (dp != null) { return FromProperty(dp, targetType); } return null; } ////// Static method that returns a DependencyPropertyDescriptor for a given property name. /// The name may refer to a direct or attached property. OwnerType is the type of /// object that owns the property definition. TargetType is the type of object you wish /// to set the property for. For direct properties, they are the same type. For attached /// properties they usually differ. /// public static DependencyPropertyDescriptor FromName(string name, Type ownerType, Type targetType, bool ignorePropertyType) { if (name == null) throw new ArgumentNullException("name"); if (ownerType == null) throw new ArgumentNullException("ownerType"); if (targetType == null) throw new ArgumentNullException("targetType"); DependencyProperty dp = DependencyProperty.FromName(name, ownerType); if (dp != null) { if (ignorePropertyType) { try { return FromProperty(dp, ownerType, targetType, ignorePropertyType); } catch (AmbiguousMatchException) { return FromProperty(dp, targetType); } } else { return FromProperty(dp, targetType); } } return null; } ////// Object.Equals override /// public override bool Equals(object obj) { DependencyPropertyDescriptor dp = obj as DependencyPropertyDescriptor; if (dp != null && dp._dp == _dp && dp._componentType == _componentType) { return true; } return false; } ////// Object.GetHashCode override /// public override int GetHashCode() { return _dp.GetHashCode() ^ _componentType.GetHashCode(); } ////// Object.ToString override /// public override string ToString() { return Name; } // // The following methods simply route to the underlying property descriptor. // ////// When overridden in a derived class, indicates whether /// the property's value can be reset to a default state. /// public override bool CanResetValue(object component) { return Property.CanResetValue(component); } ////// When overridden in a derived class, gets the current /// value of the property on a component. /// public override object GetValue(object component) { return Property.GetValue(component); } ////// When overridden in a derived class, resets the /// value for this property of the component. /// public override void ResetValue(object component) { Property.ResetValue(component); } ////// When overridden in a derived class, sets the value of /// the component to a different value. /// public override void SetValue(object component, object value) { Property.SetValue(component, value); } ////// When overridden in a derived class, indicates whether the /// value of this property needs to be persisted. /// public override bool ShouldSerializeValue(object component) { return Property.ShouldSerializeValue(component); } ////// Allows interested objects to be notified when this property changes. /// public override void AddValueChanged(object component, EventHandler handler) { Property.AddValueChanged(component, handler); } ////// Allows interested objects to be notified when this property changes. /// public override void RemoveValueChanged(object component, EventHandler handler) { Property.RemoveValueChanged(component, handler); } ////// Retrieves the properties /// public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter) { return Property.GetChildProperties(instance, filter); } ////// Gets an editor of the specified type. /// public override object GetEditor(Type editorBaseType) { return Property.GetEditor(editorBaseType); } #endregion Public Methods //------------------------------------------------------ // // Public Properties // //----------------------------------------------------- #region Public Properties ////// Returns the raw dependency property, or null if the property /// this wraps is not a dependency property. /// public DependencyProperty DependencyProperty { get { return _dp; } } ////// True if the dependency property is being attached to the target type. /// public bool IsAttached { get { return _isAttached; } } ////// The property metadata for the dependency property. This can be null if there is /// no metadata or if there is no dependency property. Values contained in property /// metadata that have matching concepts in CLR attributes are re-exposed as attributes /// in the property descriptor's Attributes collection. /// public PropertyMetadata Metadata { get { return _metadata; } } // // The following properties simply route to the underlying property descriptor. // ////// When overridden in a derived class, gets the type of the /// component this property /// is bound to. /// public override Type ComponentType { get { return _componentType; } } ////// When overridden in a derived class, gets a value /// indicating whether this property is read-only. /// public override bool IsReadOnly { get { return Property.IsReadOnly; } } ////// When overridden in a derived class, /// gets the type of the property. /// public override Type PropertyType { get { return _dp.PropertyType; } } ////// Gets the collection of attributes for this member. /// public override AttributeCollection Attributes { get { return Property.Attributes; } } ////// Gets the name of the category that the /// member belongs to, as specified in the CategoryAttribute. /// public override string Category { get { return Property.Category; } } ////// Gets the description of /// the member as specified in the DescriptionAttribute. /// public override string Description { get { return Property.Description; } } ////// Determines whether this member should be set only at /// design time as specified in the DesignOnlyAttribute. /// public override bool DesignTimeOnly { get { return Property.DesignTimeOnly; } } ////// Gets the name that can be displayed in a window like a /// properties window. /// public override string DisplayName { get { return Property.DisplayName; } } ////// Gets the type converter for this property. /// public override TypeConverter Converter { get { // We only support public type converters, in order to avoid asserts. TypeConverter typeConverter = Property.Converter; if( typeConverter.GetType().IsPublic ) { return typeConverter; } else { return null; } } } ////// Gets a value indicating whether the member is browsable as specified in the /// BrowsableAttribute. /// public override bool IsBrowsable { get { return Property.IsBrowsable; } } ////// Gets a value indicating whether this property should be localized, as /// specified in the LocalizableAttribute. /// public override bool IsLocalizable { get { return Property.IsLocalizable; } } ////// Indicates whether value change notifications for this property may originate from outside the property /// descriptor, such as from the component itself (value=true), or whether notifications will only originate /// from direct calls made to PropertyDescriptor.SetValue (value=false). For example, the component may /// implement the INotifyPropertyChanged interface, or may have an explicit '{name}Changed' event for this property. /// public override bool SupportsChangeEvents { get { return Property.SupportsChangeEvents; } } ////// This is the callback designers use to participate in the computation of property /// values at design time. Eg. Even if the author sets Visibility to Hidden, the designer /// wants to coerce the value to Visible at design time so that the element doesn't /// disappear from the design surface. /// public CoerceValueCallback DesignerCoerceValueCallback { get { return DependencyProperty.DesignerCoerceValueCallback; } set { DependencyProperty.DesignerCoerceValueCallback = value; } } #endregion Public Properties //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods ////// This method is called when we should clear our cached state. The cache /// may become invalid if someone adds additional type description providers. /// internal static void ClearCache() { lock (_cache) { _cache.Clear(); } } #endregion Internal Methods //----------------------------------------------------- // // Private Properties // //------------------------------------------------------ #region Private Properties // Return the property descriptor we're wrapping. We may have to get // this on demand if it wasn't passed into our constructor ////// Critical: calls TypeDescriptor.CreateProperty which LinkDemands /// TreatAsSafe: ok to create a property since we should have one anyway /// private PropertyDescriptor Property { [SecurityCritical, SecurityTreatAsSafe] get { if (_property == null) { _property = TypeDescriptor.GetProperties(_componentType)[Name]; if (_property == null) { // This should not normally happen. If it does, it means // that someone has messed around with metadata and has // removed this property from the type's metadata. We know // that there is really a CLR property, however, because // we are dealing with a direct property (only direct // properties can have their property descriptor delay // loaded). So, we can magically create one directly // from the CLR property through TypeDescriptor. _property = TypeDescriptor.CreateProperty(_componentType, Name, _dp.PropertyType); } } return _property; } } #endregion Private Properties //----------------------------------------------------- // // Private Fields // //----------------------------------------------------- #region Private Fields private PropertyDescriptor _property; private Type _componentType; private DependencyProperty _dp; private bool _isAttached; private PropertyMetadata _metadata; // Synchronized by "_cache" private static Dictionary
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CompilerErrorCollection.cs
- RecordsAffectedEventArgs.cs
- FlowDocument.cs
- ImageIndexConverter.cs
- TopClause.cs
- IPAddress.cs
- VisualStyleTypesAndProperties.cs
- processwaithandle.cs
- CookieParameter.cs
- DataGridColumnCollection.cs
- InputLanguageManager.cs
- ServiceProviders.cs
- Exceptions.cs
- ConfigurationManagerHelper.cs
- SystemIPAddressInformation.cs
- RelationshipWrapper.cs
- AvTraceFormat.cs
- TraceSection.cs
- SqlNotificationEventArgs.cs
- WebBaseEventKeyComparer.cs
- SatelliteContractVersionAttribute.cs
- ArrayWithOffset.cs
- ExceptionList.cs
- DateTimeValueSerializer.cs
- CustomPopupPlacement.cs
- Symbol.cs
- FamilyTypeface.cs
- SimpleTableProvider.cs
- DecimalFormatter.cs
- XPathNode.cs
- Rectangle.cs
- EventMappingSettings.cs
- MsmqEncryptionAlgorithm.cs
- sapiproxy.cs
- MultiAsyncResult.cs
- SimpleParser.cs
- QueryResults.cs
- XXXInfos.cs
- IndexingContentUnit.cs
- TemplateBuilder.cs
- BinaryObjectWriter.cs
- ExtensionWindow.cs
- SystemMulticastIPAddressInformation.cs
- ScrollBarAutomationPeer.cs
- GridLength.cs
- DatagridviewDisplayedBandsData.cs
- SafeNativeMethods.cs
- MatrixCamera.cs
- HttpRuntime.cs
- ProvidePropertyAttribute.cs
- Guid.cs
- EncryptedXml.cs
- OraclePermission.cs
- IgnoreDeviceFilterElement.cs
- XhtmlBasicFormAdapter.cs
- ActionMismatchAddressingException.cs
- SelectManyQueryOperator.cs
- InputProcessorProfiles.cs
- DataServiceRequestOfT.cs
- AstTree.cs
- DataMemberFieldEditor.cs
- MessageQueueCriteria.cs
- Calendar.cs
- HwndMouseInputProvider.cs
- SettingsPropertyValue.cs
- RelationshipSet.cs
- XpsSerializerFactory.cs
- SharedConnectionListener.cs
- InfoCardArgumentException.cs
- TailCallAnalyzer.cs
- ImageIndexConverter.cs
- UInt64Storage.cs
- DbConnectionFactory.cs
- SpeakInfo.cs
- AnchoredBlock.cs
- XmlSerializerOperationGenerator.cs
- BufferModesCollection.cs
- SupportsEventValidationAttribute.cs
- DataGridViewUtilities.cs
- EventDescriptor.cs
- ExtensionMethods.cs
- TrustLevel.cs
- MetadataItem_Static.cs
- ChannelTokenTypeConverter.cs
- TreeNodeEventArgs.cs
- UriTemplateEquivalenceComparer.cs
- WindowsListView.cs
- SoapParser.cs
- WorkflowCreationContext.cs
- DATA_BLOB.cs
- NonceCache.cs
- InstanceNameConverter.cs
- SocketException.cs
- SerializationObjectManager.cs
- ItemCollection.cs
- ReflectionPermission.cs
- ACE.cs
- OrderingQueryOperator.cs
- AliasExpr.cs
- LoginStatusDesigner.cs