File: Base\System\Windows\AttachedPropertyBrowsableForTypeAttribute.cs
Project: wpf\src\WindowsBase.csproj (WindowsBase)

namespace System.Windows 
{
    using System;
 
    /// <summary>
    ///     This class declares that an attached property is browsable only 
    ///     for dependency objects that derive from the given type.  If more 
    ///     than one type is specified, the property is browsable if any type 
    ///     matches (logical or).  The type may also be an interface.
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public sealed class AttachedPropertyBrowsableForTypeAttribute : AttachedPropertyBrowsableAttribute 
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
        
        
        /// <summary>
        ///     Creates a new AttachedPropertyBrowsableForTypeAttribute.  Provide the type
        ///     you want the attached property to be browsable for.  Multiple
        ///     attributes may be used to provide support for more than one
        ///     type.
        /// </summary>
        public AttachedPropertyBrowsableForTypeAttribute(Type targetType)
        {
            if (targetType == null) throw new ArgumentNullException("targetType");
            _targetType = targetType;
        }
        
 
        //------------------------------------------------------
        //
        //  Public Properties
        //
        //------------------------------------------------------
 
 
        /// <summary>
        ///     Returns the type passed into the constructor.
        /// </summary>
        public Type TargetType
        {
            get
            {
                return _targetType;
            }
        }
    
 
        /// <summary>
        ///     For AllowMultiple attributes, TypeId must be unique for
        ///     each unique instance.  The default returns the type, which
        ///     is only correct for AllowMultiple == false.
        /// </summary>
        public override object TypeId
        {
            get
            {
                return this;
            }
        }
 
 
        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------
 
        /// <summary>
        ///     Overrides Object.Equals to implement correct equality semantics for this
        ///     attribute.
        /// </summary>
        public override bool Equals(object obj) 
        {
            AttachedPropertyBrowsableForTypeAttribute other = obj as AttachedPropertyBrowsableForTypeAttribute;
            if (other == null) return false;
            return _targetType == other._targetType;
        }
 
        /// <summary>
        ///     Overrides Object.GetHashCode to implement correct hashing semantics.
        /// </summary>
        public override int GetHashCode() 
        {
            return _targetType.GetHashCode();
        }
 
 
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
 
    
        /// <summary>
        ///     Returns true if the dependency object passed to the method is a type, 
        ///     subtype or implememts the interface of any of the the types contained 
        ///     in this object.
        /// </summary>
        internal override bool IsBrowsable(DependencyObject d, DependencyProperty dp)
        {
            if (d == null) throw new ArgumentNullException("d");
            if (dp == null) throw new ArgumentNullException("dp");
 
            // Get the dependency object type for our target type.
            // We cannot assume the user didn't do something wrong and
            // feed us a type that is not a dependency object, but that is
            // rare enough that it is worth the try/catch here rather than
            // a double IsAssignableFrom (one here, and one in DependencyObjectType).
            // We still use a flag here rather than checking for a null
            // _dTargetType so that a bad property that throws won't consistently
            // slow the system down with ArgumentExceptions.
 
            if (!_dTargetTypeChecked) 
            {
                try
                {
                    _dTargetType = DependencyObjectType.FromSystemType(_targetType);
                }
                catch(ArgumentException)
                {
                }
 
                _dTargetTypeChecked = true;
            }
 
 
            if (_dTargetType != null && _dTargetType.IsInstanceOfType(d)) 
            {
                return true;
            }
 
            return false;
        }
 
        /// <summary>
        ///     Returns true if a browsable match is true if any one of multiple
        ///     instances of the same type return true for IsBrowsable.  We override
        ///     this to return true because any one of a successfull match for 
        ///     IsBrowsable is accepted.
        /// </summary>
        internal override bool UnionResults
        {
            get
            {
                return true;
            }
        }
    
        //------------------------------------------------------
        //
        //  Private Fields
        //
        //------------------------------------------------------
 
        private Type _targetType;
        private DependencyObjectType _dTargetType;
        private bool _dTargetTypeChecked;
    }
}