DependencyObjectProvider.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / ComponentModel / DependencyObjectProvider.cs / 1305600 / DependencyObjectProvider.cs

                            namespace MS.Internal.ComponentModel
{
    using MS.Internal.ComponentModel;
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Diagnostics;
    using System.Reflection; 
    using System.Windows;
    using System.Windows.Markup;
    using System.Text;
 
    /// 
    ///     A type description provider provides metadata for types.  It allows a type 
    ///     to define its own semantic layer for properties, events and attributes. 
    ///
    ///     Note: This class can stay internal.  To utilize it, the following 
    ///     metadata attribute should be added to DependencyObject:
    ///
    ///     [TypeDescriptionProvider(typeof(DependencyObjectProvider))]
    ///     public class DependencyObject {} 
    /// 
    internal sealed class DependencyObjectProvider : TypeDescriptionProvider { 
 
        //------------------------------------------------------
        // 
        //  Constructors
        //
        //-----------------------------------------------------
 
        #region Constructors
 
        ///  
        ///     The ctor for this class needs to be public because it is created
        ///     by TypeDescriptor using reflection. 
        /// 
        public DependencyObjectProvider() : base(TypeDescriptor.GetProvider(typeof(DependencyObject)))
        {
            // We keep a lot of caches around.  When TypeDescriptor gets a refresh 
            // we clear our caches.  We only need to do this if the refresh
            // contains type information, because we only keep static per-type 
            // caches. 

            TypeDescriptor.Refreshed += delegate(RefreshEventArgs args) 
            {
                if (args.TypeChanged != null && typeof(DependencyObject).IsAssignableFrom(args.TypeChanged))
                {
                    ClearCache(); 
                    DependencyObjectPropertyDescriptor.ClearCache();
                    DPCustomTypeDescriptor.ClearCache(); 
                    DependencyPropertyDescriptor.ClearCache(); 

                } 
            };
        }

        #endregion Constructors 

        //----------------------------------------------------- 
        // 
        //  Public Methods
        // 
        //-----------------------------------------------------

        #region Public Methods
 
        /// 
        ///     Returns a custom type descriptor suitable for querying about the 
        ///     given object type and instance. 
        /// 
        public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) 
        {
            return new DPCustomTypeDescriptor(base.GetTypeDescriptor(objectType, instance),
                objectType, instance);
        } 

        ///  
        ///     Returns a custom type descriptor suitable for querying about "extended" 
        ///     properties.  Extended properties are are attached properties in our world.
        ///  
        public override ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
        {
            ICustomTypeDescriptor descriptor = base.GetExtendedTypeDescriptor(instance);
 
            // It is possible that a Type object worked its way in here as an instance.
            // If it did, we don't need our own descriptor because we don't support 
            // attached properties on type instances. 

            if (instance != null && !(instance is Type)) 
            {
                descriptor = new APCustomTypeDescriptor(descriptor, instance);
            }
 
            return descriptor;
        } 
 
        /// 
        ///     Returns a caching layer type descriptor will use to store 
        ///     computed metadata.
        /// 
        public override IDictionary GetCache(object instance)
        { 
            DependencyObject d = instance as DependencyObject;
 
            // This should never happen because we are bound only 
            // to dependency object types.  However, in case it
            // does, simply invoke the base and get out. 

            if (d == null)
            {
                return base.GetCache(instance); 
            }
 
            // The cache we return is used by TypeDescriptor to 
            // store cached metadata information.  We demand create
            // it here. 
            // If the DependencyObject is Sealed we cannot store
            // the cache on it - if no cache exists already we
            // will return null.
 
            IDictionary cache = _cacheSlot.GetValue(d);
            if (cache == null && !d.IsSealed) 
            { 
                cache = new Hashtable();
                _cacheSlot.SetValue(d, cache); 
            }

            return cache;
        } 

        #endregion Public Methods 
 
        //------------------------------------------------------
        // 
        //  Public Properties
        //
        //-----------------------------------------------------
 

        //------------------------------------------------------ 
        // 
        //  Public Events
        // 
        //------------------------------------------------------


        //----------------------------------------------------- 
        //
        //  Private Methods 
        // 
        //------------------------------------------------------
 
        #region Private Methods

        /// 
        ///     This method is called when we should clear our cached state.  The cache 
        ///     may become invalid if someone adds additional type description providers.
        ///  
        private static void ClearCache() 
        {
            lock (_propertyMap) 
            {
                _propertyMap.Clear();
            }
 
            lock(_propertyKindMap)
            { 
                _propertyKindMap.Clear(); 
            }
 
            lock(_attachInfoMap)
            {
                _attachInfoMap.Clear();
            } 
        }
 
        ///  
        ///     This method calculates the attach rules defined on
        ///     this dependency property.  It always returns a valid 
        ///     AttachInfo, but the fields in AttachInfo may be null.
        /// 
        internal static AttachInfo GetAttachInfo(DependencyProperty dp)
        { 
            // Have we already seen this DP?
            AttachInfo info = (AttachInfo)_attachInfoMap[dp]; 
 
            if (info == null)
            { 
                info = new AttachInfo(dp);

                lock(_attachInfoMap)
                { 
                    _attachInfoMap[dp] = info;
                } 
            } 

            return info; 
        }

        #endregion Private Methods
 

        //----------------------------------------------------- 
        // 
        //  Internal Methods
        // 
        //-----------------------------------------------------

        #region Internal Methods
 
        /// 
        ///     This method returns an attached property descriptor for the given DP and target type. 
        ///  
        internal static DependencyObjectPropertyDescriptor GetAttachedPropertyDescriptor(DependencyProperty dp, Type targetType)
        { 
            DependencyObjectPropertyDescriptor dpProp;
            PropertyKey key = new PropertyKey(targetType, dp);

            lock(_propertyMap) 
            {
                if (!_propertyMap.TryGetValue(key, out dpProp)) 
                { 
                    dpProp = new DependencyObjectPropertyDescriptor(dp, targetType);
                    _propertyMap[key] = dpProp; 
                }
            }

            return dpProp; 
        }
 
        ///  
        ///     This method returns a DependencyPropertyKind object which can
        ///     be used to tell if a given DP / target type combination represents 
        ///     an attached or direct property.
        /// 
        internal static DependencyPropertyKind GetDependencyPropertyKind(DependencyProperty dp, Type targetType)
        { 
            DependencyPropertyKind kind;
            PropertyKey key = new PropertyKey(targetType, dp); 
 
            lock(_propertyKindMap)
            { 
                if (!_propertyKindMap.TryGetValue(key, out kind))
                {
                    kind = new DependencyPropertyKind(dp, targetType);
                    _propertyKindMap[key] = kind; 
                }
            } 
 
            return kind;
        } 

        #endregion Internal Methods

        //----------------------------------------------------- 
        //
        //  Private Fields 
        // 
        //------------------------------------------------------
 
        #region Private Fields

        private static readonly UncommonField _cacheSlot = new UncommonField(null);
 
        // Synchronized by "_propertyMap"
        private static Dictionary _propertyMap = new Dictionary(); 
 
        // Synchronized by "_propertyKindMap"
        private static Dictionary _propertyKindMap = new Dictionary(); 

        // Synchronized by "_attachInfoMap"
        private static Hashtable _attachInfoMap = new Hashtable();
 
        #endregion Private Fields
    } 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK