|
namespace MS.Internal.ComponentModel
{
using System;
using System.Windows;
//
// Determines what kind of DP we are dealing with. DependencyPropertyKind
// is associated with a target type and a DP. It calculates IsAttached
// and IsDirect on demand using the following rules:
//
// IsAttached is true iff:
//
// 1. The target type is not a registered owner of the DP, or
// the target type is the DP's owner type.
//
// 2. The DP's owner type offers a public static Get method
// with the same name as the DP. The method must
// have the correct signature (one parameter that derives
// from DependencyObject).
//
// IsDirect is true iff:
//
// 1. The target type is a registered owner of the DP.
//
// 2. The target type offers a public CLR property of the
// same name as the DP.
//
// If neither of these is true the property is assumed to be internal
// and therefore inaccessible to anyone via reflection.
//
// A property cannot be both attached and direct. If a property defines
// both accessors direct accessors take precidence.
//
internal class DependencyPropertyKind
{
//------------------------------------------------------
//
// Internal Constructors
//
//------------------------------------------------------
//
// Creates a new instance
//
internal DependencyPropertyKind(DependencyProperty dp, Type targetType)
{
_dp = dp;
_targetType = targetType;
}
//------------------------------------------------------
//
// Internal Properties
//
//------------------------------------------------------
//
// Returns true if the property is internal.
//
internal bool IsInternal
{
get
{
if (!_isInternalChecked)
{
// The property is internal if it has no public
// static Get method or no public CLR accessor. If we already
// calculated it to be a direct or attached property, bail because
// it's clearly not internal.
if (!_isAttached && !_isDirect)
{
if (DependencyObjectPropertyDescriptor.GetAttachedPropertyMethod(_dp) == null &&
_dp.OwnerType.GetProperty(_dp.Name, _dp.PropertyType) == null)
{
_isInternal = true;
}
}
_isInternalChecked = true;
}
return _isInternal;
}
}
//
// Returns true if the property is attached for the target type.
//
internal bool IsAttached
{
get
{
if (!_isAttachedChecked)
{
// A property cannot be both attached and direct,
// so if this property is already direct we have our
// answer. Note that we check the IsDirect property
// here to force evaluation. Direct takes precidence
// over attached on the same object, so we need to
// force the check if it hasn't been done.
if (!IsDirect)
{
// If the attached property is AddOwnered to this type, we
// don't treat it as attached because, by definition, attached
// properties can only have one owner, and any AddOwnered version
// beceomes a direct property.
if (_dp.OwnerType == _targetType || _dp.OwnerType.IsAssignableFrom(_targetType) || DependencyProperty.FromName(_dp.Name, _targetType) != _dp)
{
if (DependencyObjectPropertyDescriptor.GetAttachedPropertyMethod(_dp) != null)
{
_isAttached = true;
}
}
}
_isAttachedChecked = true;
}
return _isAttached;
}
}
//
// Returns true if the property is direct for the target type.
//
internal bool IsDirect
{
get
{
if (!_isDirectChecked)
{
// If we've already calculated attached, we
// know the answer if _isAttached is true because
// a property cannot be both.
// No need to also check _isAttachedChecked since this will
// only be true if the check has been done.
if (!_isAttached)
{
if (DependencyProperty.FromName(_dp.Name, _targetType) == _dp)
{
if (_targetType.GetProperty(_dp.Name, _dp.PropertyType) != null)
{
_isDirect = true;
_isAttachedChecked = true;
}
}
}
_isDirectChecked = true;
}
return _isDirect;
}
}
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
private readonly DependencyProperty _dp;
private readonly Type _targetType;
private bool _isAttached;
private bool _isAttachedChecked;
private bool _isInternal;
private bool _isInternalChecked;
private bool _isDirect;
private bool _isDirectChecked;
}
}
|