Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Base / System / Windows / DependencyProperty.cs / 3 / DependencyProperty.cs
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; using System.Globalization; using System.ComponentModel; using System.Windows.Markup;// For ValueSerializerAttribute using System.Windows.Threading; // For DispatcherObject using System.Security.Permissions; // For LinkDemand using MS.Utility; using MS.Internal.WindowsBase; using System.Reflection; // for IsInstanceOfType using MS.Internal; #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace System.Windows { ////// An attached dependency-based property /// [TypeConverter("System.Windows.Markup.DependencyPropertyConverter, PresentationFramework, Version=" + Microsoft.Internal.BuildInfo.WCP_VERSION + ", Culture=neutral, PublicKeyToken=" + Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_TOKEN + ", Custom=null")] [ValueSerializer(typeof(DependencyPropertyValueSerializer))] public sealed class DependencyProperty { ////// Register a Dependency Property /// /// Name of property /// Type of the property /// Type that is registering the property ///Dependency Property public static DependencyProperty Register(string name, Type propertyType, Type ownerType) { // Forwarding return Register(name, propertyType, ownerType, null, null); } ////// Register a Dependency Property /// /// Name of property /// Type of the property /// Type that is registering the property /// Metadata to use if current type doesn't specify type-specific metadata ///Dependency Property public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata) { // Forwarding return Register(name, propertyType, ownerType, typeMetadata, null); } ////// Register a Dependency Property /// /// Name of property /// Type of the property /// Type that is registering the property /// Metadata to use if current type doesn't specify type-specific metadata /// Provides additional value validation outside automatic type validation ///Dependency Property public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback) { RegisterParameterValidation(name, propertyType, ownerType); // Register an attached property PropertyMetadata defaultMetadata = null; if (typeMetadata != null && typeMetadata.DefaultValueWasSet()) { defaultMetadata = new PropertyMetadata(typeMetadata.DefaultValue); } DependencyProperty property = RegisterCommon(name, propertyType, ownerType, defaultMetadata, validateValueCallback); if (typeMetadata != null) { // Apply type-specific metadata to owner type only property.OverrideMetadata(ownerType, typeMetadata); } return property; } ////// Simple registration, metadata, validation, and a read-only property /// key. Calling this version restricts the property such that it can /// only be set via the corresponding overload of DependencyObject.SetValue. /// public static DependencyPropertyKey RegisterReadOnly( string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata ) { return RegisterReadOnly( name, propertyType, ownerType, typeMetadata, null ); } ////// Simple registration, metadata, validation, and a read-only property /// key. Calling this version restricts the property such that it can /// only be set via the corresponding overload of DependencyObject.SetValue. /// public static DependencyPropertyKey RegisterReadOnly( string name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback ) { RegisterParameterValidation(name, propertyType, ownerType); PropertyMetadata defaultMetadata = null; if (typeMetadata != null && typeMetadata.DefaultValueWasSet()) { defaultMetadata = new PropertyMetadata(typeMetadata.DefaultValue); } else { defaultMetadata = AutoGeneratePropertyMetadata(propertyType,validateValueCallback,name,ownerType); } // We create a DependencyPropertyKey at this point with a null property // and set that in the _readOnlyKey field. This is so the property is // marked as requiring a key immediately. If something fails in the // initialization path, the property is still marked as needing a key. // This is better than the alternative of creating and setting the key // later, because if that code fails the read-only property would not // be marked read-only. The intent of this mildly convoluted code // is so we fail securely. DependencyPropertyKey authorizationKey = new DependencyPropertyKey(null); // No property yet, use null as placeholder. DependencyProperty property = RegisterCommon(name, propertyType, ownerType, defaultMetadata, validateValueCallback); property._readOnlyKey = authorizationKey; authorizationKey.SetDependencyProperty(property); if (typeMetadata == null ) { // No metadata specified, generate one so we can specify the authorized key. typeMetadata = AutoGeneratePropertyMetadata(propertyType,validateValueCallback,name,ownerType); } // Authorize registering type for read-only access, create key. #pragma warning suppress 6506 // typeMetadata is never null, since we generate default metadata if none is provided. // Apply type-specific metadata to owner type only property.OverrideMetadata(ownerType, typeMetadata, authorizationKey); return authorizationKey; } ////// Simple registration, metadata, validation, and a read-only property /// key. Calling this version restricts the property such that it can /// only be set via the corresponding overload of DependencyObject.SetValue. /// public static DependencyPropertyKey RegisterAttachedReadOnly(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata) { return RegisterAttachedReadOnly( name, propertyType, ownerType, defaultMetadata, null ); } ////// Simple registration, metadata, validation, and a read-only property /// key. Calling this version restricts the property such that it can /// only be set via the corresponding overload of DependencyObject.SetValue. /// public static DependencyPropertyKey RegisterAttachedReadOnly(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback) { RegisterParameterValidation(name, propertyType, ownerType); // Establish default metadata for all types, if none is provided if (defaultMetadata == null) { defaultMetadata = AutoGeneratePropertyMetadata( propertyType, validateValueCallback, name, ownerType ); } // We create a DependencyPropertyKey at this point with a null property // and set that in the _readOnlyKey field. This is so the property is // marked as requiring a key immediately. If something fails in the // initialization path, the property is still marked as needing a key. // This is better than the alternative of creating and setting the key // later, because if that code fails the read-only property would not // be marked read-only. The intent of this mildly convoluted code // is so we fail securely. DependencyPropertyKey authorizedKey = new DependencyPropertyKey(null); DependencyProperty property = RegisterCommon( name, propertyType, ownerType, defaultMetadata, validateValueCallback); property._readOnlyKey = authorizedKey; authorizedKey.SetDependencyProperty(property); return authorizedKey; } ////// Register an attached Dependency Property /// /// Name of property /// Type of the property /// Type that is registering the property ///Dependency Property public static DependencyProperty RegisterAttached(string name, Type propertyType, Type ownerType) { // Forwarding return RegisterAttached(name, propertyType, ownerType, null, null ); } ////// Register an attached Dependency Property /// /// Name of property /// Type of the property /// Type that is registering the property /// Metadata to use if current type doesn't specify type-specific metadata ///Dependency Property public static DependencyProperty RegisterAttached(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata) { // Forwarding return RegisterAttached(name, propertyType, ownerType, defaultMetadata, null ); } ////// Register an attached Dependency Property /// /// Name of property /// Type of the property /// Type that is registering the property /// Metadata to use if current type doesn't specify type-specific metadata /// Provides additional value validation outside automatic type validation ///Dependency Property public static DependencyProperty RegisterAttached(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback) { RegisterParameterValidation(name, propertyType, ownerType); return RegisterCommon( name, propertyType, ownerType, defaultMetadata, validateValueCallback ); } private static void RegisterParameterValidation(string name, Type propertyType, Type ownerType) { if (name == null) { throw new ArgumentNullException("name"); } if (name.Length == 0) { throw new ArgumentException(SR.Get(SRID.StringEmpty), "name"); } if (ownerType == null) { throw new ArgumentNullException("ownerType"); } if (propertyType == null) { throw new ArgumentNullException("propertyType"); } } private static DependencyProperty RegisterCommon(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback) { FromNameKey key = new FromNameKey(name, ownerType); lock (Synchronized) { if (PropertyFromName.Contains(key)) { throw new ArgumentException(SR.Get(SRID.PropertyAlreadyRegistered, name, ownerType.Name)); } } // Establish default metadata for all types, if none is provided if (defaultMetadata == null) { defaultMetadata = AutoGeneratePropertyMetadata( propertyType, validateValueCallback, name, ownerType ); } else // Metadata object is provided. { // If the defaultValue wasn't specified auto generate one if (!defaultMetadata.DefaultValueWasSet()) { defaultMetadata.DefaultValue = AutoGenerateDefaultValue(propertyType); } ValidateMetadataDefaultValue( defaultMetadata, propertyType, name, validateValueCallback ); } // Create property DependencyProperty dp = new DependencyProperty(name, propertyType, ownerType, defaultMetadata, validateValueCallback); // Seal (null means being used for default metadata, calls OnApply) defaultMetadata.Seal(dp, null); if (defaultMetadata.IsInherited) { dp._packedData |= Flags.IsPotentiallyInherited; } if (defaultMetadata.UsingDefaultValueFactory) { dp._packedData |= Flags.IsPotentiallyUsingDefaultValueFactory; } // Map owner type to this property // Build key lock (Synchronized) { PropertyFromName[key] = dp; } if( TraceDependencyProperty.IsEnabled ) { TraceDependencyProperty.TraceActivityItem( TraceDependencyProperty.Register, dp, dp.OwnerType ); } return dp; } private static object AutoGenerateDefaultValue( Type propertyType) { // Default per-type metadata not provided, create object defaultValue = null; // Auto-assigned default value if (propertyType.IsValueType) { // Value-types have default-constructed type default values defaultValue = Activator.CreateInstance(propertyType); } return defaultValue; } private static PropertyMetadata AutoGeneratePropertyMetadata( Type propertyType, ValidateValueCallback validateValueCallback, string name, Type ownerType) { // Default per-type metadata not provided, create object defaultValue = AutoGenerateDefaultValue(propertyType); // If a validator is passed in, see if the default value makes sense. if ( validateValueCallback != null && !validateValueCallback(defaultValue)) { // Didn't work - require the caller to specify one. throw new ArgumentException(SR.Get(SRID.DefaultValueAutoAssignFailed, name, ownerType.Name)); } return new PropertyMetadata(defaultValue); } // Validate the default value in the given metadata private static void ValidateMetadataDefaultValue( PropertyMetadata defaultMetadata, Type propertyType, string propertyName, ValidateValueCallback validateValueCallback ) { // If we are registered to use the DefaultValue factory we can // not validate the DefaultValue at registration time, so we // early exit. if (defaultMetadata.UsingDefaultValueFactory) { return; } ValidateDefaultValueCommon(defaultMetadata.DefaultValue, propertyType, propertyName, validateValueCallback, /*checkThreadAffinity = */ true); } // Validate the given default value, used by PropertyMetadata.GetDefaultValue() // when the DefaultValue factory is used. // These default values are allowed to have thread-affinity. internal void ValidateFactoryDefaultValue(object defaultValue) { ValidateDefaultValueCommon(defaultValue, PropertyType, Name, ValidateValueCallback, false); } private static void ValidateDefaultValueCommon( object defaultValue, Type propertyType, string propertyName, ValidateValueCallback validateValueCallback, bool checkThreadAffinity) { // Ensure default value is the correct type if (!IsValidType(defaultValue, propertyType)) { throw new ArgumentException(SR.Get(SRID.DefaultValuePropertyTypeMismatch, propertyName)); } // An Expression used as default value won't behave as expected since // it doesn't get evaluated. We explicitly fail it here. if (defaultValue is Expression ) { throw new ArgumentException(SR.Get(SRID.DefaultValueMayNotBeExpression)); } if (checkThreadAffinity) { // If the default value is a DispatcherObject with thread affinity // we cannot accept it as a default value. If it implements ISealable // we attempt to seal it; if not we throw an exception. Types not // deriving from DispatcherObject are allowed - it is up to the user to // make any custom types free-threaded. DispatcherObject dispatcherObject = defaultValue as DispatcherObject; if (dispatcherObject != null && dispatcherObject.Dispatcher != null) { // Try to make the DispatcherObject free-threaded if it's an // ISealable. ISealable valueAsISealable = dispatcherObject as ISealable; if (valueAsISealable != null && valueAsISealable.CanSeal) { Invariant.Assert (!valueAsISealable.IsSealed, "A Sealed ISealable must not have dispatcher affinity"); valueAsISealable.Seal(); Invariant.Assert(dispatcherObject.Dispatcher == null, "ISealable.Seal() failed after ISealable.CanSeal returned true"); } else { throw new ArgumentException(SR.Get(SRID.DefaultValueMustBeFreeThreaded, propertyName)); } } } // After checking for correct type, check default value against // validator (when one is given) if ( validateValueCallback != null && !validateValueCallback(defaultValue)) { throw new ArgumentException(SR.Get(SRID.DefaultValueInvalid, propertyName)); } } ////// Parameter validation for OverrideMetadata, includes code to force /// all base classes of "forType" to register their metadata so we know /// what we are overriding. /// private void SetupOverrideMetadata( Type forType, PropertyMetadata typeMetadata, out DependencyObjectType dType, out PropertyMetadata baseMetadata ) { if (forType == null) { throw new ArgumentNullException("forType"); } if (typeMetadata == null) { throw new ArgumentNullException("typeMetadata"); } if (typeMetadata.Sealed) { throw new ArgumentException(SR.Get(SRID.TypeMetadataAlreadyInUse)); } if (!typeof(DependencyObject).IsAssignableFrom(forType)) { throw new ArgumentException(SR.Get(SRID.TypeMustBeDependencyObjectDerived, forType.Name)); } // Ensure default value is a correct value (if it was supplied, // otherwise, the default value will be taken from the base metadata // which was already validated) if (typeMetadata.IsDefaultValueModified) { // Will throw ArgumentException if fails. ValidateMetadataDefaultValue( typeMetadata, PropertyType, Name, ValidateValueCallback ); } // Force all base classes to register their metadata dType = DependencyObjectType.FromSystemType(forType); // Get metadata for the base type baseMetadata = GetMetadata(dType.BaseType); // Make sure overriding metadata is the same type or derived type of // the base metadata if (!baseMetadata.GetType().IsAssignableFrom(typeMetadata.GetType())) { throw new ArgumentException(SR.Get(SRID.OverridingMetadataDoesNotMatchBaseMetadataType)); } } ////// Supply metadata for given type /// ////// The supplied metadata will be merged with the type's base /// metadata /// /// Type to associate metadata /// The metadata to use public void OverrideMetadata(Type forType, PropertyMetadata typeMetadata) { DependencyObjectType dType; PropertyMetadata baseMetadata; SetupOverrideMetadata( forType, typeMetadata, out dType, out baseMetadata ); if( ReadOnly ) { // Readonly and no DependencyPropertyKey - not allowed. throw new InvalidOperationException(SR.Get(SRID.ReadOnlyOverrideNotAllowed, Name)); } ProcessOverrideMetadata( forType, typeMetadata, dType, baseMetadata ); } ////// Supply metadata for a given type, overriding a property that is /// read-only. If property is not read only, tells user to use the Plain /// Jane OverrideMetadata instead. /// public void OverrideMetadata(Type forType, PropertyMetadata typeMetadata, DependencyPropertyKey key) { DependencyObjectType dType; PropertyMetadata baseMetadata; SetupOverrideMetadata( forType, typeMetadata, out dType, out baseMetadata ); if( key == null ) { throw new ArgumentNullException("key"); } if( ReadOnly ) { // If the property is read-only, the key must match this property // and the key must match that in the base metadata. if( key.DependencyProperty != this ) { throw new ArgumentException(SR.Get(SRID.ReadOnlyOverrideKeyNotAuthorized, Name)); } VerifyReadOnlyKey(key); } else { throw new InvalidOperationException(SR.Get(SRID.PropertyNotReadOnly)); } // Either the property doesn't require a key, or the key match was // successful. Proceed with the metadata override. ProcessOverrideMetadata( forType, typeMetadata, dType, baseMetadata ); } ////// After parameters have been validated for OverrideMetadata, this /// method is called to actually update the data structures. /// private void ProcessOverrideMetadata( Type forType, PropertyMetadata typeMetadata, DependencyObjectType dType, PropertyMetadata baseMetadata) { // Store per-Type metadata for this property. Locks only on Write. // Datastructure guaranteed to be valid for non-locking readers lock (Synchronized) { if (DependencyProperty.UnsetValue == _metadataMap[dType.Id]) { _metadataMap[dType.Id] = typeMetadata; } else { throw new ArgumentException(SR.Get(SRID.TypeMetadataAlreadyRegistered, forType.Name)); } } // Merge base's metadata into this metadata // CALLBACK typeMetadata.InvokeMerge(baseMetadata, this); // Type metadata may no longer change (calls OnApply) typeMetadata.Seal(this, forType); if (typeMetadata.IsInherited) { _packedData |= Flags.IsPotentiallyInherited; } if (typeMetadata.DefaultValueWasSet() && (typeMetadata.DefaultValue != DefaultMetadata.DefaultValue)) { _packedData |= Flags.IsDefaultValueChanged; } if (typeMetadata.UsingDefaultValueFactory) { _packedData |= Flags.IsPotentiallyUsingDefaultValueFactory; } } [FriendAccessAllowed] // Built into Base, also used by Core & Framework. internal object GetDefaultValue(DependencyObjectType dependencyObjectType) { if (!IsDefaultValueChanged) { return DefaultMetadata.DefaultValue; } return GetMetadata(dependencyObjectType).DefaultValue; } [FriendAccessAllowed] // Built into Base, also used by Core & Framework. internal object GetDefaultValue(Type forType) { if (!IsDefaultValueChanged) { return DefaultMetadata.DefaultValue; } return GetMetadata(DependencyObjectType.FromSystemTypeInternal(forType)).DefaultValue; } ////// Retrieve metadata for a provided type /// /// Type to get metadata ///Property metadata public PropertyMetadata GetMetadata(Type forType) { if (forType != null) { return GetMetadata(DependencyObjectType.FromSystemType(forType)); } throw new ArgumentNullException("forType"); } ////// Retrieve metadata for a provided DependencyObject /// /// DependencyObject to get metadata ///Property metadata public PropertyMetadata GetMetadata(DependencyObject dependencyObject) { if (dependencyObject != null) { return GetMetadata(dependencyObject.DependencyObjectType); } throw new ArgumentNullException("dependencyObject"); } ////// Reteive metadata for a DependencyObject type described by the /// given DependencyObjectType /// //CASRemoval:[StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey = Microsoft.Internal.BuildInfo.WCP_PUBLIC_KEY_STRING)] public PropertyMetadata GetMetadata(DependencyObjectType dependencyObjectType) { // All static constructors for this DType and all base types have already // been run. If no overriden metadata was provided, then look up base types. // If no metadata found on base types, then return default if (null != dependencyObjectType) { // Do we in fact have any overrides at all? int index = _metadataMap.Count - 1; int Id; object value; if (index < 0) { // No overrides or it's the base class return _defaultMetadata; } else if (index == 0) { // Only 1 override _metadataMap.GetKeyValuePair(index, out Id, out value); // If there is overriden metadata, then there is a base class with // lower or equal Id of this class, or this class is already a base class // of the overridden one. Therefore dependencyObjectType won't ever // become null before we exit the while loop while (dependencyObjectType.Id > Id) { dependencyObjectType = dependencyObjectType.BaseType; } if (Id == dependencyObjectType.Id) { // Return the override return (PropertyMetadata)value; } // Return default metadata } else { // We have more than 1 override for this class, so we will have to loop through // both the overrides and the class Id if (0 != dependencyObjectType.Id) { do { // Get the Id of the most derived class with overridden metadata _metadataMap.GetKeyValuePair(index, out Id, out value); --index; // If the Id of this class is less than the override, then look for an override // with an equal or lower Id until we run out of overrides while ((dependencyObjectType.Id < Id) && (index >= 0)) { _metadataMap.GetKeyValuePair(index, out Id, out value); --index; } // If there is overriden metadata, then there is a base class with // lower or equal Id of this class, or this class is already a base class // of the overridden one. Therefore dependencyObjectType won't ever // become null before we exit the while loop while (dependencyObjectType.Id > Id) { dependencyObjectType = dependencyObjectType.BaseType; } if (Id == dependencyObjectType.Id) { // Return the override return (PropertyMetadata)value; } } while (index >= 0); } } } return _defaultMetadata; } ////// Associate another owner type with this property /// ////// The owner type is used when resolving a property by name ( /// Additional owner type ///) /// This property public DependencyProperty AddOwner(Type ownerType) { // Forwarding return AddOwner(ownerType, null); } ////// Associate another owner type with this property /// ////// The owner type is used when resolving a property by name ( /// Additional owner type /// Optional type metadata to override on owner's behalf ///) /// This property public DependencyProperty AddOwner(Type ownerType, PropertyMetadata typeMetadata) { if (ownerType == null) { throw new ArgumentNullException("ownerType"); } // Map owner type to this property // Build key FromNameKey key = new FromNameKey(Name, ownerType); lock (Synchronized) { if (PropertyFromName.Contains(key)) { throw new ArgumentException(SR.Get(SRID.PropertyAlreadyRegistered, Name, ownerType.Name)); } } if (typeMetadata != null) { OverrideMetadata(ownerType, typeMetadata); } lock (Synchronized) { PropertyFromName[key] = this; } return this; } ////// Name of the property /// public string Name { get { return _name; } } ////// Type of the property /// public Type PropertyType { get { return _propertyType; } } ////// Owning type of the property /// public Type OwnerType { get { return _ownerType; } } ////// Default metadata for the property /// public PropertyMetadata DefaultMetadata { get { return _defaultMetadata; } } ////// Value validation callback /// public ValidateValueCallback ValidateValueCallback { get { return _validateValueCallback; } } ////// Zero-based globally unique index of the property /// public int GlobalIndex { get { return (int) (_packedData & Flags.GlobalIndexMask); } } internal bool IsObjectType { get { return (_packedData & Flags.IsObjectType) != 0; } } internal bool IsValueType { get { return (_packedData & Flags.IsValueType) != 0; } } internal bool IsFreezableType { get { return (_packedData & Flags.IsFreezableType) != 0; } } internal bool IsStringType { get { return (_packedData & Flags.IsStringType) != 0; } } internal bool IsPotentiallyInherited { get { return (_packedData & Flags.IsPotentiallyInherited) != 0; } } internal bool IsDefaultValueChanged { get { return (_packedData & Flags.IsDefaultValueChanged) != 0; } } internal bool IsPotentiallyUsingDefaultValueFactory { get { return (_packedData & Flags.IsPotentiallyUsingDefaultValueFactory) != 0; } } ////// Serves as a hash function for a particular type, suitable for use in /// hashing algorithms and data structures like a hash table /// ///The DependencyProperty's GlobalIndex public override int GetHashCode() { return GlobalIndex; } ////// Used to determine if given value is appropriate for the type of the property /// /// Value to check ///true if value matches property type public bool IsValidType(object value) { return IsValidType(value, PropertyType); } ////// Used to determine if given value is appropriate for the type of the property /// and the range of values (as specified via the ValidateValueCallback) within that type /// /// Value to check ///true if value is appropriate public bool IsValidValue(object value) { if (!IsValidType(value, PropertyType)) { return false; } if (ValidateValueCallback != null) { // CALLBACK return ValidateValueCallback(value); } return true; } ////// Set/Value value disabling /// public bool ReadOnly { get { return (_readOnlyKey != null); } } internal void VerifyReadOnlyKey( DependencyPropertyKey candidateKey ) { Debug.Assert( ReadOnly, "Why are we trying to validate read-only key on a property that is not read-only?"); if (_readOnlyKey != candidateKey) { throw new ArgumentException(SR.Get(SRID.ReadOnlyKeyNotAuthorized)); } } ////// Internal version of IsValidValue that bypasses IsValidType check; /// Called from SetValueInternal /// /// Value to check ///true if value is appropriate internal bool IsValidValueInternal(object value) { if (ValidateValueCallback != null) { // CALLBACK return ValidateValueCallback(value); } return true; } ////// Find a property from name /// ////// Search includes base classes of the provided type as well /// /// Name of the property /// Owner type of the property ///Dependency property [FriendAccessAllowed] // Built into Base, also used by Framework. internal static DependencyProperty FromName(string name, Type ownerType) { DependencyProperty dp = null; if (name != null) { if (ownerType != null) { FromNameKey key = new FromNameKey(name, ownerType); while ((dp == null) && (ownerType != null)) { // Ensure static constructor of type has run RuntimeHelpers.RunClassConstructor(ownerType.TypeHandle); // Locate property key.UpdateNameKey(ownerType); lock (Synchronized) { dp = (DependencyProperty)PropertyFromName[key]; } ownerType = ownerType.BaseType; } } else { throw new ArgumentNullException("ownerType"); } } else { throw new ArgumentNullException("name"); } return dp; } ////// String representation /// public override string ToString() { return _name; } internal static bool IsValidType(object value, Type propertyType) { if (value == null) { // Null values are invalid for value-types if (propertyType.IsValueType && !(propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == NullableType)) { return false; } } else { // Non-null default value, ensure its the correct type if (!propertyType.IsInstanceOfType(value)) { return false; } } return true; } private class FromNameKey { public FromNameKey(string name, Type ownerType) { _name = name; _ownerType = ownerType; _hashCode = _name.GetHashCode() ^ _ownerType.GetHashCode(); } public void UpdateNameKey(Type ownerType) { _ownerType = ownerType; _hashCode = _name.GetHashCode() ^ _ownerType.GetHashCode(); } public override int GetHashCode() { return _hashCode; } public override bool Equals(object o) { if ((o != null) && (o is FromNameKey)) { return Equals((FromNameKey)o); } else { return false; } } public bool Equals(FromNameKey key) { return (_name.Equals(key._name) && (_ownerType == key._ownerType)); } private string _name; private Type _ownerType; private int _hashCode; } private DependencyProperty(string name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback) { _name = name; _propertyType = propertyType; _ownerType = ownerType; _defaultMetadata = defaultMetadata; _validateValueCallback = validateValueCallback; Flags packedData; lock (Synchronized) { packedData = (Flags) GetUniqueGlobalIndex(ownerType, name); RegisteredPropertyList.Add(this); } if (propertyType.IsValueType) { packedData |= Flags.IsValueType; } if (propertyType == typeof(object)) { packedData |= Flags.IsObjectType; } if (typeof(Freezable).IsAssignableFrom(propertyType)) { packedData |= Flags.IsFreezableType; } if (propertyType == typeof(string)) { packedData |= Flags.IsStringType; } _packedData = packedData; } // Synchronized: Covered by DependencyProperty.Synchronized internal static int GetUniqueGlobalIndex(Type ownerType, string name) { // Prevent GlobalIndex from overflow. DependencyProperties are meant to be static members and are to be registered // only via static constructors. However there is no cheap way of ensuring this, without having to do a stack walk. Hence // concievably people could register DependencyProperties via instance methods and therefore cause the GlobalIndex to // overflow. This check will explicitly catch this error, instead of silently malfuntioning. if (GlobalIndexCount >= (int)Flags.GlobalIndexMask) { if (ownerType != null) { throw new InvalidOperationException(SR.Get(SRID.TooManyDependencyProperties, ownerType.Name + "." + name)); } else { throw new InvalidOperationException(SR.Get(SRID.TooManyDependencyProperties, "ConstantProperty")); } } // Covered by Synchronized by caller return GlobalIndexCount++; } ////// 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. /// internal CoerceValueCallback DesignerCoerceValueCallback { get { return _designerCoerceValueCallback; } set { if (ReadOnly) { throw new InvalidOperationException(SR.Get(SRID.ReadOnlyDesignerCoersionNotAllowed, Name)); } _designerCoerceValueCallback = value; } } ///Standard unset value public static readonly object UnsetValue = new NamedObject("DependencyProperty.UnsetValue"); private string _name; private Type _propertyType; private Type _ownerType; private PropertyMetadata _defaultMetadata; private ValidateValueCallback _validateValueCallback; private DependencyPropertyKey _readOnlyKey; [Flags] private enum Flags : int { GlobalIndexMask = 0x0000FFFF, IsValueType = 0x00010000, IsFreezableType = 0x00020000, IsStringType = 0x00040000, IsPotentiallyInherited = 0x00080000, IsDefaultValueChanged = 0x00100000, IsPotentiallyUsingDefaultValueFactory = 0x00200000, IsObjectType = 0x00400000, // 0xFF800000 free bits } private Flags _packedData; // Synchronized (write locks, lock-free reads): Covered by DependencyProperty instance // This is a map that contains the IDs of derived classes that have overriden metadata /* property */ internal InsertionSortMap _metadataMap = new InsertionSortMap(); private CoerceValueCallback _designerCoerceValueCallback; // Synchronized (write locks, lock-free reads): Covered by DependencyProperty.Synchronized /* property */ internal static ItemStructListRegisteredPropertyList = new ItemStructList (768); // Synchronized: Covered by DependencyProperty.Synchronized private static Hashtable PropertyFromName = new Hashtable(); // Synchronized: Covered by DependencyProperty.Synchronized private static int GlobalIndexCount; // Global, cross-object synchronization internal static object Synchronized = new object(); // Nullable Type private static Type NullableType = typeof(Nullable<>); /// /// Returns the number of all registered properties. /// internal static int RegisteredPropertyCount { get { return RegisteredPropertyList.Count; } } ////// Returns an enumeration of properties that are /// currently registered. /// Synchronized (write locks, lock-free reads): Covered by DependencyProperty.Synchronized /// /* The C# compiler produces bad symbols for this property, that can cause ILDASM to crash (DDB 194064). To avoid this, we explicitly write the code the compiler would normally generate. (The compiler bug is related to the "yield return" feature, so we just hand-compile it. See DDB 202629.) internal static IEnumerable RegisteredProperties { get { foreach(DependencyProperty dp in RegisteredPropertyList.List) { if (dp != null) { yield return dp; } } } } The following code imitates what the compiler generates for this property (as reported by Reflector) as closely as possible. Consequently it may look a little odd. There are some IL constructs that have no direct C# equivalent; I have supplied the closest imitation I could for these: a) try...fault b) goto into a case arm */ internal static IEnumerable RegisteredProperties { get { return new RegisteredPropertiesEnumerable(-2); } } private sealed class RegisteredPropertiesEnumerable : IEnumerable
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DocumentOrderComparer.cs
- ArraySegment.cs
- _ShellExpression.cs
- SqlException.cs
- Grammar.cs
- Semaphore.cs
- ContainerFilterService.cs
- HotCommands.cs
- RequestSecurityTokenResponse.cs
- AllMembershipCondition.cs
- SQLDecimalStorage.cs
- RemoteWebConfigurationHostServer.cs
- ImmutableObjectAttribute.cs
- BoolExpr.cs
- Renderer.cs
- TextProperties.cs
- GeneralTransform.cs
- TypeBinaryExpression.cs
- UInt16Storage.cs
- MenuStrip.cs
- XpsS0ValidatingLoader.cs
- ToolTip.cs
- Site.cs
- PreloadHost.cs
- ModuleConfigurationInfo.cs
- ChangePassword.cs
- ExpressionVisitor.cs
- Cursors.cs
- ApplicationFileCodeDomTreeGenerator.cs
- ListQueryResults.cs
- MD5Cng.cs
- UpWmlPageAdapter.cs
- InternalRelationshipCollection.cs
- DocumentEventArgs.cs
- ClientRuntimeConfig.cs
- IgnoreDeviceFilterElementCollection.cs
- FlowDocumentFormatter.cs
- File.cs
- DataGridCellAutomationPeer.cs
- QilGenerator.cs
- AppDomainManager.cs
- DrawingContext.cs
- DataTableTypeConverter.cs
- ParagraphVisual.cs
- SignatureToken.cs
- HtmlContainerControl.cs
- ActivityInstance.cs
- HttpServerVarsCollection.cs
- DataGridViewColumnCollection.cs
- ReadingWritingEntityEventArgs.cs
- DBBindings.cs
- SimpleWebHandlerParser.cs
- RegexCode.cs
- MaterialCollection.cs
- ConditionedDesigner.cs
- metadatamappinghashervisitor.cs
- TextBreakpoint.cs
- SiteMapNode.cs
- SymbolPair.cs
- __FastResourceComparer.cs
- DynamicValueConverter.cs
- BlockCollection.cs
- HttpPostedFile.cs
- SystemException.cs
- ZipIOEndOfCentralDirectoryBlock.cs
- SoapUnknownHeader.cs
- DataGridViewControlCollection.cs
- WebScriptMetadataMessageEncodingBindingElement.cs
- _LocalDataStoreMgr.cs
- StateMachine.cs
- Size3DConverter.cs
- BooleanToVisibilityConverter.cs
- PropertyKey.cs
- PersistencePipeline.cs
- ViewBase.cs
- WmpBitmapEncoder.cs
- BulletChrome.cs
- FactorySettingsElement.cs
- PixelFormatConverter.cs
- ObjectDataSourceStatusEventArgs.cs
- Pen.cs
- ErrorHandlerFaultInfo.cs
- WindowsFormsLinkLabel.cs
- SchemaTypeEmitter.cs
- XmlProcessingInstruction.cs
- CipherData.cs
- ImageClickEventArgs.cs
- SubstitutionList.cs
- HttpDigestClientCredential.cs
- DebugHandleTracker.cs
- CallTemplateAction.cs
- TextLineResult.cs
- OperationAbortedException.cs
- x509store.cs
- SortedSet.cs
- EventPropertyMap.cs
- AnnotationHelper.cs
- HostedTcpTransportManager.cs
- MessageRpc.cs
- BinaryObjectWriter.cs