APCustomTypeDescriptor.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Base / MS / Internal / ComponentModel / APCustomTypeDescriptor.cs / 1 / APCustomTypeDescriptor.cs

                            namespace 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;

 
    /// 
    ///     This class is a custom type descriptor for attached dependency properties.  We 
    ///     could just inherit from the CustomTypeDescriptor class, which does most of the forwarding 
    ///     work for us, but these are allocated a lot so we want them to be structs.
    ///  
    struct APCustomTypeDescriptor : ICustomTypeDescriptor {

        //------------------------------------------------------
        // 
        //  Constructors
        // 
        //----------------------------------------------------- 

        #region Constructors 

        /// 
        ///     Creates a new APCustomTypeDescriptor.  We pass in the custom type descriptor of
        ///     our base provider, which provides is with a default implementation of everything 
        ///     we don't override.  for us, we want to override only the property mechanism.
        ///  
        internal APCustomTypeDescriptor(ICustomTypeDescriptor parent, object instance) 
        {
            _parent = parent; 
            _instance = FromObj(instance);
        }

        #endregion Constructors 

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

        #region Public Methods
 
        /// 
        ///     Returns a collection of properties for our object.  We first rely on base 
        ///     CLR properties and then we attempt to match these with dependency properties. 
        /// 
        public PropertyDescriptorCollection GetProperties() 
        {
            return GetProperties(null);
        }
 
        /// 
        ///     Returns a collection of properties for our object.  We first rely on base 
        ///     CLR properties and then we attempt to match these with dependency properties. 
        /// 
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes) 
        {

            // Because attached properties can come and go at any time,
            // the set of properties we have here always needs to be rebuilt. 

            // We have two code paths here based on filtered attributes.  An attribute 
            // filter is just a notificaiton of a filter, it doesn't actually perform 
            // the filter.  Because the default PropertyFilterAttribute is PropertyFilter.All,
            // it acts as a nice "don't care" in later filtering stages that TypeDescriptor 
            // may apply.  That means that regardless of the filter value, we don't have
            // to fiddle with adding the attribute to the property descriptor.

            PropertyFilterOptions filter = PropertyFilterOptions.Valid | PropertyFilterOptions.SetValues; 

            if (attributes != null) 
            { 
                foreach (Attribute attr in attributes)
                { 
                    PropertyFilterAttribute filterAttr = attr as PropertyFilterAttribute;
                    if (filterAttr != null)
                    {
                        filter = filterAttr.Filter; 
                        break;
                    } 
                } 
            }
 
            if (filter == PropertyFilterOptions.None)
            {
                return PropertyDescriptorCollection.Empty;
            } 

            // First, get the set of all known registered properties in the 
            // app domain.  GetRegisteredProperties caches its results and 
            // will automatically re-fetch if new properties have been
            // registered 
            DependencyProperty[] registeredProperties = GetRegisteredProperties();
            Type instanceType = _instance.GetType();

            // Next, walk through them and see which ones can be attached to this 
            // object.  If our filter is specifically SetValues, we can
            // greatly shortcut the entire process by using the local value 
            // enumerator. 

            List filteredProps; 

            if (filter == PropertyFilterOptions.SetValues)
            {
                LocalValueEnumerator localEnum = _instance.GetLocalValueEnumerator(); 
                filteredProps = new List(localEnum.Count);
 
                while(localEnum.MoveNext()) 
                {
                    DependencyProperty dp = localEnum.Current.Property; 
                    DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType);

                    // For locally set values, we just want to exclude direct and internal properties.
                    if (!kind.IsDirect && !kind.IsInternal) 
                    {
                        DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType); 
                        filteredProps.Add(dpProp); 
                    }
                } 
            }
            else
            {
                filteredProps = new List(registeredProperties.Length); 

                foreach (DependencyProperty dp in registeredProperties) 
                { 
                    bool addProp = false;
                    DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType); 

                    if (kind.IsAttached)
                    {
 
                        // Check bit combinations that would yield true in
                        // any case.  For non-attached properties, they're all valid, so if 
                        // the valid bit is set, we're done. 

                        PropertyFilterOptions anySet = PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues; 
                        PropertyFilterOptions anyValid = PropertyFilterOptions.Valid | PropertyFilterOptions.Invalid;

                        if ((filter & anySet) == anySet || (filter & anyValid) == anyValid)
                        { 
                            addProp = true;
                        } 
 
                        if (!addProp && (filter & anyValid) != 0)
                        { 
                            bool canAttach = CanAttachProperty(dp, _instance);
                            addProp = canAttach ^ ((filter & anyValid) == PropertyFilterOptions.Invalid);
                        }
 

                        if (!addProp && (filter & anySet) != 0) 
                        { 
                            bool shouldSerialize = _instance.ContainsValue(dp);
                            addProp = shouldSerialize ^ ((filter & anySet) == PropertyFilterOptions.UnsetValues); 
                        }
                    }
                    else if ((filter & PropertyFilterOptions.SetValues) != 0 && _instance.ContainsValue(dp) && !kind.IsDirect && !kind.IsInternal)
                    { 

                        // The property is not attached.  However, it isn't an internal DP and the user 
                        // has requested set values.  See if the property is set on the object and include 
                        // it if it is.
                        addProp = true; 
                    }

                    if (addProp)
                    { 
                        DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType);
                        filteredProps.Add(dpProp); 
                    } 
                }
            } 

            PropertyDescriptorCollection properties;
            properties = new PropertyDescriptorCollection(filteredProps.ToArray(), true);
            return properties; 
        }
 
        // 
        // All methods below simply forward to the parent descriptor.
        // 

        public AttributeCollection GetAttributes() { return _parent.GetAttributes(); }
        public string GetClassName() { return _parent.GetClassName(); }
        public string GetComponentName() { return _parent.GetComponentName(); } 

        public TypeConverter GetConverter() 
        { 
            // We only support public type converters, in order to avoid asserts.
            TypeConverter typeConverter = _parent.GetConverter(); 
            if( typeConverter.GetType().IsPublic )
            {
                return typeConverter;
            } 
            else
            { 
                return null; 
            }
        } 
        public EventDescriptor GetDefaultEvent() { return _parent.GetDefaultEvent(); }
        public PropertyDescriptor GetDefaultProperty() { return _parent.GetDefaultProperty(); }
        public object GetEditor(Type editorBaseType) { return _parent.GetEditor(editorBaseType); }
        public EventDescriptorCollection GetEvents() { return _parent.GetEvents(); } 
        public EventDescriptorCollection GetEvents(Attribute[] attributes) { return _parent.GetEvents(attributes); }
        public object GetPropertyOwner(PropertyDescriptor property) { return _parent.GetPropertyOwner(property); } 
 
        #endregion Public Methods
 
        //------------------------------------------------------
        //
        //  Private Methods
        // 
        //-----------------------------------------------------
 
        #region Private Methods 

        ///  
        ///     This method determines if the given property can be attached
        ///     to the given instance.
        /// 
        private bool CanAttachProperty(DependencyProperty dp, DependencyObject instance) 
        {
            AttachInfo info = DependencyObjectProvider.GetAttachInfo(dp); 
            return info.CanAttach(instance); 
        }
 
        /// 
        ///     Returns a dependency object for the given value.
        /// 
        private static DependencyObject FromObj(object value) 
        {
            // This indirection is necessary to support 
            // the "association" feature of type descriptor.  This feature 
            // alows one object to mimic the API of another.
            return (DependencyObject)TypeDescriptor.GetAssociation(typeof(DependencyObject), value); 
        }

        /// 
        ///     Returns an array of all registered properties declared in the 
        ///     system.
        ///  
        private DependencyProperty[] GetRegisteredProperties() 
        {
            DependencyProperty[] registeredProperties; 

            // We keep track of the global dependency property count.
            // Because DPs are never removed, we use this value to
            // verify if our cache of registered properties is up to date. 
            // If the count doesn't match our cached count, we re-fetch
            // all registered properties. 
 
            lock(_syncLock)
            { 
                int cacheCnt = _dpCacheCount;
                int currentCnt = DependencyProperty.RegisteredPropertyCount;

                if (_dpCacheArray == null || cacheCnt != currentCnt) 
                {
                    List dpList = new List(currentCnt); 
                    lock(DependencyProperty.Synchronized) 
                    {
                        foreach(DependencyProperty dp in DependencyProperty.RegisteredProperties) 
                        {
                            dpList.Add(dp);
                        }
 
                        _dpCacheCount = DependencyProperty.RegisteredPropertyCount;
                        _dpCacheArray = dpList.ToArray(); 
                    } 
                }
 
                registeredProperties = _dpCacheArray;
            }

            return registeredProperties; 
        }
 
        #endregion Private Methods 

        //------------------------------------------------------ 
        //
        //  Private Fields
        //
        //------------------------------------------------------ 

        #region Private Fields 
 

        private ICustomTypeDescriptor _parent; 
        private DependencyObject _instance;

        private static object _syncLock = new object();
 
        // Synchronized by "_syncLock"
        private static int _dpCacheCount = 0; 
 
        // Synchronized by "_syncLock"
        private static DependencyProperty[] _dpCacheArray; 

        #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