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 ItemStructList RegisteredPropertyList = 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
- SessionState.cs
- DataGridViewCellStateChangedEventArgs.cs
- FormattedTextSymbols.cs
- InvalidEnumArgumentException.cs
- FormsAuthentication.cs
- ADConnectionHelper.cs
- DocumentGridPage.cs
- MessageTraceRecord.cs
- DesignerAdapterAttribute.cs
- AddInAdapter.cs
- Accessible.cs
- HtmlTableCell.cs
- WorkflowApplicationException.cs
- InkCanvasFeedbackAdorner.cs
- AlphabeticalEnumConverter.cs
- ListView.cs
- GridViewEditEventArgs.cs
- SendMailErrorEventArgs.cs
- WindowsHyperlink.cs
- DateTimeOffset.cs
- DurableEnlistmentState.cs
- MultilineStringConverter.cs
- MenuItemBinding.cs
- Container.cs
- QilStrConcatenator.cs
- Rotation3D.cs
- HelpExampleGenerator.cs
- RenamedEventArgs.cs
- ToolStripSplitButton.cs
- ToolStripPanelRow.cs
- _IPv4Address.cs
- ETagAttribute.cs
- ComPlusSynchronizationContext.cs
- RecoverInstanceLocksCommand.cs
- ObjectResult.cs
- ParenthesizePropertyNameAttribute.cs
- ItemCheckedEvent.cs
- EntityUtil.cs
- XmlQualifiedName.cs
- EntityException.cs
- HelpInfo.cs
- ImportCatalogPart.cs
- CrossSiteScriptingValidation.cs
- GACIdentityPermission.cs
- TreeIterator.cs
- AsymmetricAlgorithm.cs
- DSASignatureDeformatter.cs
- TypeConverter.cs
- EntityClassGenerator.cs
- ByteKeyFrameCollection.cs
- CryptoKeySecurity.cs
- Interlocked.cs
- UnionExpr.cs
- ControlIdConverter.cs
- Int16Converter.cs
- SystemFonts.cs
- StatusBarPanelClickEvent.cs
- PropertyDescriptorCollection.cs
- DecodeHelper.cs
- Metadata.cs
- DesignerActionPanel.cs
- CompressionTracing.cs
- SQLBinary.cs
- SoapSchemaExporter.cs
- TreeNode.cs
- TreeNodeStyleCollection.cs
- ToolStripStatusLabel.cs
- FileEnumerator.cs
- BitmapEffectGeneralTransform.cs
- CodeThrowExceptionStatement.cs
- BaseAddressPrefixFilterElement.cs
- CompressionTransform.cs
- MruCache.cs
- Condition.cs
- ReturnValue.cs
- BamlLocalizer.cs
- HierarchicalDataBoundControl.cs
- AuthorizationRuleCollection.cs
- UIPropertyMetadata.cs
- JsonStringDataContract.cs
- XmlFileEditor.cs
- CodeLabeledStatement.cs
- EntityDataSource.cs
- DefaultAutoFieldGenerator.cs
- baseaxisquery.cs
- AbandonedMutexException.cs
- WebRequestModulesSection.cs
- DataSourceSelectArguments.cs
- ConstraintEnumerator.cs
- SHA256.cs
- LoginName.cs
- ConstraintStruct.cs
- ImageField.cs
- HuffCodec.cs
- PropertyPathConverter.cs
- GetIsBrowserClientRequest.cs
- Vector3DConverter.cs
- ChangeTracker.cs
- Publisher.cs
- XmlNotation.cs