DependencyObjectPropertyDescriptor.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 / DependencyObjectPropertyDescriptor.cs / 1305600 / DependencyObjectPropertyDescriptor.cs

                             
namespace MS.Internal.ComponentModel
{
    using System;
    using System.Collections; 
    using System.Collections.Generic;
    using System.ComponentModel; 
    using System.Diagnostics; 
    using System.Globalization;
    using System.Reflection; 
    using System.Security.Permissions;
    using System.Windows;
    using System.Security;
    using SR=MS.Internal.WindowsBase.SR; 
    using SRID=MS.Internal.WindowsBase.SRID;
 
 
    /// 
    ///     An inplementation of a property descriptor for DependencyProperties. 
    ///     This supports both normal and attached properties.
    /// 
    internal sealed class DependencyObjectPropertyDescriptor : PropertyDescriptor {
 
        //------------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 

        #region Constructors

        ///  
        ///     Creates a new dependency property descriptor.  A note on perf:  We don't
        ///     pass the property descriptor down as the default member descriptor here.  Doing 
        ///     so takes the attributes off of the property descriptor, which can be costly if they 
        ///     haven't been accessed yet.  Instead, we wait until someone needs to access our
        ///     Attributes property and demand create the attributes at that time. 
        /// 
        internal DependencyObjectPropertyDescriptor(PropertyDescriptor property, DependencyProperty dp, Type objectType)
            : base(dp.Name, null)
        { 
            _property = property;
            _dp = dp; 
 
            Debug.Assert(property != null && dp != null);
            Debug.Assert(!(property is DependencyObjectPropertyDescriptor), "Wrapping a DP in a DP"); 

            _componentType = property.ComponentType;
            _metadata = _dp.GetMetadata(objectType);
        } 

        ///  
        ///     Creates a new dependency property descriptor.  A note on perf:  We don't 
        ///     pass the property descriptor down as the default member descriptor here.  Doing
        ///     so takes the attributes off of the property descriptor, which can be costly if they 
        ///     haven't been accessed yet.  Instead, we wait until someone needs to access our
        ///     Attributes property and demand create the attributes at that time.
        /// 
        internal DependencyObjectPropertyDescriptor(DependencyProperty dp, Type ownerType) 
            : base(string.Concat(dp.OwnerType.Name, ".", dp.Name), null)
        { 
            _dp = dp; 
            _componentType = ownerType;
            _metadata = _dp.GetMetadata(ownerType); 
        }

        #endregion Constructors
 

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

        #region Public Methods
 
        /// 
        ///     Indicates if this property's value can be reset. 
        ///     We map this to true if there is a local value 
        ///     on the DP.
        ///  
        public override bool CanResetValue(object component)
        {
            // All DPs that have values set can be reset
            return ShouldSerializeValue(component); 
        }
 
        ///  
        ///     Returns the value for this property.
        ///  
        public override object GetValue(object component)
        {
            DependencyObject DO = FromObj(component);
            return DO.GetValue(_dp); 
        }
 
        ///  
        ///     Attempts to reset (or clear) the value in the
        ///     DP. 
        /// 
        public override void ResetValue(object component)
        {
            if (!_queriedResetMethod) 
            {
                _resetMethod = GetSpecialMethod("Reset"); 
                _queriedResetMethod = true; 
            }
 
            DependencyObject DO = FromObj(component);

            if (_resetMethod != null)
            { 
                // See if we need to pass parameters to this method.  When
                // _property == null, this is an attached property and 
                // the method is static.  When _property != null, this 
                // is a direct property and the method is instanced.
 
                if (_property == null)
                {
                    _resetMethod.Invoke(null, new object[] {DO});
                } 
                else
                { 
                    _resetMethod.Invoke(DO, null); 
                }
            } 
            else
            {
                DO.ClearValue(_dp);
            } 
        }
 
        ///  
        ///     Sets the property value on the given object.
        ///  
        public override void SetValue(object component, object value)
        {
            DependencyObject DO = FromObj(component);
            DO.SetValue(_dp, value); 
        }
 
        ///  
        ///     Returns true if the property contains
        ///     a local value that should be serialized. 
        /// 
        public override bool ShouldSerializeValue(object component)
        {
            DependencyObject DO = FromObj(component); 
            bool shouldSerialize = DO.ShouldSerializeProperty(_dp);
 
            // The of precedence is that a property should be serialized if the ShouldSerializeProperty 
            // method returns true and either ShouldSerializeXXX does not exist or it exists and returns true.
 
            if (shouldSerialize)
            {
                // If we have a ShouldSerialize method, use it
 
                if (!_queriedShouldSerializeMethod)
                { 
                    MethodInfo method = GetSpecialMethod("ShouldSerialize"); 

                    if (method != null && method.ReturnType == BoolType) 
                    {
                        _shouldSerializeMethod = method;
                    }
                    _queriedShouldSerializeMethod = true; 
                }
 
                if (_shouldSerializeMethod != null) 
                {
                    // See if we need to pass parameters to this method.  When 
                    // _property == null, this is an attached property and
                    // the method is static.  When _property != null, this
                    // is a direct property and the method is instanced.
 
                    if (_property == null)
                    { 
                        shouldSerialize = (bool)_shouldSerializeMethod.Invoke(null, new object[] {DO}); 
                    }
                    else 
                    {
                        shouldSerialize = (bool)_shouldSerializeMethod.Invoke(DO, null);
                    }
                } 
            }
 
            return shouldSerialize; 
        }
 
        /// 
        ///     Adds a change event handler to this descriptor.
        /// 
        public override void AddValueChanged(object component, EventHandler handler) 
        {
            // 
 

            DependencyObject DO = FromObj(component); 
            if (_trackers == null)
            {
                _trackers = new Dictionary();
            } 

            PropertyChangeTracker tracker; 
            if (!_trackers.TryGetValue(DO, out tracker)) 
            {
                tracker = new PropertyChangeTracker(DO, _dp); 
                _trackers.Add(DO, tracker);
            }

            tracker.Changed += handler; 
        }
 
        ///  
        ///     Removes a previously added change handler.
        ///  
        public override void RemoveValueChanged(object component, EventHandler handler) {
            if (_trackers == null) return;
            PropertyChangeTracker tracker;
            DependencyObject DO = FromObj(component); 

            if (_trackers.TryGetValue(DO, out tracker)) 
            { 
                tracker.Changed -= handler;
                if (tracker.CanClose) 
                {
                    tracker.Close();
                    _trackers.Remove(DO);
                } 
            }
        } 
 

        #endregion Public Methods 

        //------------------------------------------------------
        //
        //  Public Properties 
        //
        //----------------------------------------------------- 
 
        #region Public Properties
 
        /// 
        ///     Returns the collection of attributes associated with this property.
        /// 
        public override AttributeCollection Attributes 
        {
            get 
            { 
                // Windows OS Bugs 1383847.  The Attributes
                // property on PropertyDescriptor is not as thread 
                // safe as it should be.  There are instances when
                // it can return null during contention.  Our fix is
                // to detect this case and lock.  Note that this isn't
                // 100% because not all property descriptors are 
                // DependencyObjectPropertyDescriptors.
 
                AttributeCollection attrs = base.Attributes; 
                if (attrs == null)
                { 
                    lock(_attributeSyncLock)
                    {
                        attrs = base.Attributes;
                        Debug.Assert(attrs != null); 
                    }
                } 
 
                return attrs;
            } 
        }

        /// 
        ///     The type of object this property is describing. 
        /// 
        public override Type ComponentType 
        { 
            get { return _componentType; }
        } 

        /// 
        ///     Returns true if the DP is read only.
        ///  
        public override bool IsReadOnly
        { 
            get { 

                // It is a lot cheaper to get DP metadata 
                // than it is to calculate attributes.  While
                // the attributes do factor in DP metadata, short
                // circuit for this common case.
                bool readOnly = _dp.ReadOnly; 
                if (!readOnly) {
                    readOnly = Attributes.Contains(ReadOnlyAttribute.Yes); 
                } 
                return readOnly;
            } 
        }

        /// 
        ///     The type of the property. 
        /// 
        public override Type PropertyType 
        { 
            get { return _dp.PropertyType; }
        } 

        /// 
        ///     Returns true if this property descriptor supports change
        ///     notifications.  All dependency property descriptors do. 
        /// 
        public override bool SupportsChangeEvents 
        { 
            get { return true; }
        } 

        #endregion Public Properties

 
        //------------------------------------------------------
        // 
        //  Internal Properties 
        //
        //------------------------------------------------------ 

        #region Internal Properties

        ///  
        ///     Returns the dependency property we're wrapping.
        ///  
        internal DependencyProperty DependencyProperty 
        {
            get { return _dp; } 
        }


        internal bool IsAttached 
        {
             get { return (_property == null); } 
        } 

        internal PropertyMetadata Metadata 
        {
            get { return _metadata; }
        }
 
        #endregion Internal Properties
 
        //----------------------------------------------------- 
        //
        //  Internal Methods 
        //
        //------------------------------------------------------

        #region Internal Methods 

        ///  
        ///     This method is called when we should clear our cached state.  The cache 
        ///     may become invalid if someone adds additional type description providers.
        ///  
        internal static void ClearCache()
        {
            lock (_getMethodCache)
            { 
                _getMethodCache.Clear();
            } 
 
            lock(_setMethodCache)
            { 
                _setMethodCache.Clear();
            }

            _dpType = null; 
            _boolType = null;
            _attributeType = null; 
            _attachedPropertyBrowsableType = null; 
        }
 
        /// 
        ///     A helper method that returns the static "Get" method for an attached
        ///     property.  The dpType parameter is the data type of the object you
        ///     want to attach the property to. 
        /// 
        internal static MethodInfo GetAttachedPropertyMethod(DependencyProperty dp) 
        { 
            // Check the cache.  This property descriptor is cached by the
            // dependency object provider, but there is a unique property descriptor 
            // for each type an attached property can be attached to.  Therefore,
            // caching this method lookup for a DP makes sense.

            MethodInfo method; 

            // TypeDescriptor offers a feature called a "reflection type", which 
            // is an indirection to another type we should reflect on.  Anywhere 
            // we rely on raw reflection we should be using GetReflectionType.
            // Also the returning type may change if someone added or removed 
            // a provider, so we need to detect this in our cache invalidation
            // logic.

            Type reflectionType = TypeDescriptor.GetReflectionType(dp.OwnerType); 

            object methodObj = _getMethodCache[dp]; 
            method = methodObj as MethodInfo; 

            if (methodObj == null || (method != null && !object.ReferenceEquals(method.DeclaringType, reflectionType))) { 
                BindingFlags f = BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly;
                string methodName = string.Concat("Get", dp.Name);
                method = reflectionType.GetMethod(methodName, f, _dpBinder, DpType, null);
 
                lock(_getMethodCache) {
                    _getMethodCache[dp] = (method == null ? _nullMethodSentinel : method); 
                } 
            }
 
            return method;
        }

        #endregion Internal Methods 

        //----------------------------------------------------- 
        // 
        //  Protected Methods
        // 
        //-----------------------------------------------------

        #region Protected Methods
 
        /// 
        ///     Overridden to lazily create our attributes. 
        ///  
        protected override AttributeCollection CreateAttributeCollection()
        { 
            MergeAttributes();
            return base.CreateAttributeCollection();
        }
 
        #endregion Protected Methods
 
 
        //-----------------------------------------------------
        // 
        //  Private Methods
        //
        //------------------------------------------------------
 
        #region Private Methods
 
        ///  
        ///     Helper method that recovers a dependency object from a 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); 
        } 

        ///  
        ///     Additional metadata attributes for attached properties
        ///     are taken from the "Get" method.
        /// 
        private AttributeCollection GetAttachedPropertyAttributes() 
        {
            MethodInfo mi = GetAttachedPropertyMethod(_dp); 
 
            if (mi != null)
            { 
                Type attrType = AttributeType;
                Attribute[] attrArray = (Attribute[])mi.GetCustomAttributes(attrType, true);

                Type propertyReflectionType = TypeDescriptor.GetReflectionType(_dp.PropertyType); 
                Attribute[] typeAttrArray = (Attribute[])propertyReflectionType.GetCustomAttributes(attrType, true);
                if (typeAttrArray != null && typeAttrArray.Length > 0) 
                { 
                    // Merge attrArry and typeAttrArray
                    Attribute[] mergedAttrArray = new Attribute[attrArray.Length + typeAttrArray.Length]; 
                    Array.Copy(attrArray, mergedAttrArray, attrArray.Length);
                    Array.Copy(typeAttrArray, 0, mergedAttrArray, attrArray.Length, typeAttrArray.Length);
                    attrArray = mergedAttrArray;
                } 

                // Look for and expand AttributeProvider attributes.  These are attributes 
                // that allow a method to adopt attributes from another location.  This 
                // allows generic properties, such as "public object DataSource {get; set;}",
                // to share a common set of attributes. 

                Attribute[] addAttrs = null;

                foreach(Attribute attr in attrArray) 
                {
                    AttributeProviderAttribute pa = attr as AttributeProviderAttribute; 
                    if (pa != null) 
                    {
                        Type providerType = Type.GetType(pa.TypeName); 
                        if (providerType != null)
                        {
                            Attribute[] paAttrs = null;
                            if (!string.IsNullOrEmpty(pa.PropertyName)) 
                            {
                                MemberInfo[] milist = providerType.GetMember(pa.PropertyName); 
                                if (milist.Length > 0 && milist[0] != null) 
                                {
                                    paAttrs = (Attribute[])milist[0].GetCustomAttributes(typeof(Attribute), true); 
                                }
                            }
                            else {
                                paAttrs = (Attribute[])providerType.GetCustomAttributes(typeof(Attribute), true); 
                            }
 
                            if (paAttrs != null) 
                            {
                                if (addAttrs == null) 
                                {
                                    addAttrs = paAttrs;
                                }
                                else 
                                {
                                    Attribute[] newArray = new Attribute[addAttrs.Length + paAttrs.Length]; 
                                    addAttrs.CopyTo(newArray, 0); 
                                    paAttrs.CopyTo(newArray, addAttrs.Length);
                                    addAttrs = newArray; 

                                }
                            }
                        } 
                    }
                } 
 
                // See if we gathered additional attributes.  These are always lower priority
                // and therefore get tacked onto the end of the list 
                if (addAttrs != null)
                {
                    Attribute[] newArray = new Attribute[addAttrs.Length + attrArray.Length];
                    attrArray.CopyTo(newArray, 0); 
                    addAttrs.CopyTo(newArray, attrArray.Length);
                    attrArray = newArray; 
                } 

                return new AttributeCollection(attrArray); 
            }

            return AttributeCollection.Empty;
        } 

        ///  
        ///     A helper method that returns the static "Get" method for an attached 
        ///     property.  The dpType parameter is the data type of the object you
        ///     want to attach the property to. 
        /// 
        private static MethodInfo GetAttachedPropertySetMethod(DependencyProperty dp)
        {
            // Check the cache.  This property descriptor is cached by the 
            // dependency object provider, but there is a unique property descriptor
            // for each type an attached property can be attached to.  Therefore, 
            // caching this method lookup for a DP makes sense. 

            MethodInfo method; 

            // TypeDescriptor offers a feature called a "reflection type", which
            // is an indirection to another type we should reflect on.  Anywhere
            // we rely on raw reflection we should be using GetReflectionType. 
            // Also the returning type may change if someone added or removed
            // a provider, so we need to detect this in our cache invalidation 
            // logic. 

            Type reflectionType = TypeDescriptor.GetReflectionType(dp.OwnerType); 

            object methodObj = _setMethodCache[dp];
            method = methodObj as MethodInfo;
 
            if (methodObj == null || (method != null && !object.ReferenceEquals(method.DeclaringType, reflectionType))) {
                BindingFlags f = BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly; 
                string methodName = string.Concat("Set", dp.Name); 

                Type[] paramTypes = new Type[] { 
                    DpType[0],
                    TypeDescriptor.GetReflectionType(dp.PropertyType)
                };
 
                method = reflectionType.GetMethod(methodName, f, _dpBinder, paramTypes, null);
 
                lock(_setMethodCache) { 
                    _setMethodCache[dp] = (method == null ? _nullMethodSentinel : method);
                } 
            }

            return method;
        } 

        ///  
        ///     Returns one of the "special" property methods for a property descriptor. 
        ///     The property name will be appended to the method prefix.  This method
        ///     is used to return the MethodInfo for ShouldSerialize(property) and 
        ///     Reset(property).
        /// 
        private MethodInfo GetSpecialMethod(string methodPrefix)
        { 
            BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic;
            Type[] types; 
            Type reflectionType; 

            if (_property == null) 
            {
                // Attached property
                types = DpType;
                flags |= BindingFlags.Static; 

                // TypeDescriptor offers a feature called a "reflection type", which 
                // is an indirection to another type we should reflect on.  Anywyere 
                // we rely on raw reflection we should be using GetReflectionType.
 
                reflectionType = TypeDescriptor.GetReflectionType(_dp.OwnerType);
            }
            else
            { 
                // Direct property
                types = Type.EmptyTypes; 
                flags |= BindingFlags.Instance; 

                // TypeDescriptor offers a feature called a "reflection type", which 
                // is an indirection to another type we should reflect on.  Anywyere
                // we rely on raw reflection we should be using GetReflectionType.

                reflectionType = TypeDescriptor.GetReflectionType(_property.ComponentType); 
            }
 
            string methodName = string.Concat(methodPrefix, _dp.Name); 

            // According to spec, ShouldSerialize and Reset can be non-public.  So we should 
            // assert ReflectionPermission here, like TypeDescriptor does.  But since every
            // assert is a security risk, we'll take the compatibility hit, and leave it out.

            MethodInfo methodInfo = reflectionType.GetMethod(methodName, flags, _dpBinder, types, null); 

            if (methodInfo != null) 
            { 
                // We don't support non-public ShouldSerialize/ClearValue methods.  We could just look
                // for public methods in the first place, but then authors might get confused as 
                // to why their non-public method didn't get found, especially because the CLR
                // TypeDescriptor does find and use non-public methods.
                if( !methodInfo.IsPublic )
                { 
                    throw new InvalidOperationException(SR.Get(SRID.SpecialMethodMustBePublic, methodInfo.Name));
                } 
            } 

            return methodInfo; 


        }
 
        /// 
        ///     This method is called on demand when we need to get at one or 
        ///     more attributes for this property.  Because obtaining attributes 
        ///     can be costly, we wait until now to do the job.
        ///  
        private void MergeAttributes()
        {
            AttributeCollection baseAttributes;
 
            if (_property != null)
            { 
                baseAttributes = _property.Attributes; 
            }
            else 
            {
                baseAttributes = GetAttachedPropertyAttributes();
            }
 
            List newAttributes = new List(baseAttributes.Count + 1);
 
            bool readOnly = false; 

            foreach (Attribute a in baseAttributes) 
            {
                Attribute attrToAdd = a;
                DefaultValueAttribute defAttr = a as DefaultValueAttribute;
 
                if (defAttr != null)
                { 
                    // DP metadata always overrides CLR metadata for 
                    // default value.
                    attrToAdd = null; 
                }
                else
                {
                    ReadOnlyAttribute roAttr = a as ReadOnlyAttribute; 
                    if (roAttr != null)
                    { 
                        // DP metata is the merge of CLR metadata for 
                        // read only
                        readOnly = roAttr.IsReadOnly; 
                        attrToAdd = null;
                    }
                }
 
                if (attrToAdd != null) newAttributes.Add(attrToAdd);
            } 
 
            // Always include the metadata choice
            readOnly |= _dp.ReadOnly; 

            // If we are an attached property and non-read only, the lack of a
            // set method will make us read only.
            if (_property == null && !readOnly && GetAttachedPropertySetMethod(_dp) == null) { 
                readOnly = true;
            } 
 
            // Add our own DependencyPropertyAttribute
            DependencyPropertyAttribute dpa = new DependencyPropertyAttribute(_dp, (_property == null)); 
            newAttributes.Add(dpa);

            // Add DefaultValueAttribute if the DP has a default
            // value 
            if (_metadata.DefaultValue != DependencyProperty.UnsetValue)
            { 
                newAttributes.Add(new DefaultValueAttribute(_metadata.DefaultValue)); 
            }
 
            // And add a read only attribute if needed
            if (readOnly)
            {
                newAttributes.Add(new ReadOnlyAttribute(true)); 
            }
 
            // Inject these attributes into our attribute array.  There 
            // is a quirk to the way this works.  Attributes as they
            // are returned by the CLR and by AttributeCollection are in 
            // priority order with the attributes at the front of the list
            // taking precidence over those at the end.  Attributes
            // handed to MemberDescriptor's AttributeArray, however, are
            // in reverse priority order so the "last one in wins".  Therefore 
            // we need to reverse the array.
 
            Attribute[] attrArray = newAttributes.ToArray(); 
            for (int idx = 0; idx < attrArray.Length / 2; idx++)
            { 
                int swap = attrArray.Length - idx - 1;
                Attribute t = attrArray[idx];
                attrArray[idx] = attrArray[swap];
                attrArray[swap] = t; 
            }
 
            AttributeArray = attrArray; 
        }
 

        #endregion Private Methods

        //----------------------------------------------------- 
        //
        //  Private Properties 
        // 
        //------------------------------------------------------
 
        #region Private Properties

        /// 
        /// Helper to get the reflection version of typeof(AttachedPropertyBrowsableAttribute).  This is used by 
        /// the AttachInfo class.
        ///  
        internal static Type AttachedPropertyBrowsableAttributeType { 
            get {
                Type attachedPropertyBrowsableType = _attachedPropertyBrowsableType; 
                if (attachedPropertyBrowsableType == null) {
                    attachedPropertyBrowsableType = TypeDescriptor.GetReflectionType(typeof(AttachedPropertyBrowsableAttribute));
                    _attachedPropertyBrowsableType = attachedPropertyBrowsableType;
                } 
                return attachedPropertyBrowsableType;
            } 
        } 

        ///  
        /// Helper to get the reflection version of typeof(Attribute)
        /// 
        private static Type AttributeType {
            get { 
                Type attributeType = _attributeType;
                if (attributeType == null) { 
                    attributeType = TypeDescriptor.GetReflectionType(typeof(Attribute)); 
                    _attributeType = attributeType;
                } 
                return attributeType;
            }
        }
 
        /// 
        /// Helper to get the reflection version of typeof(bool) 
        ///  
        private static Type BoolType {
            get { 
                Type boolType = _boolType;
                if (boolType == null) {
                    boolType = TypeDescriptor.GetReflectionType(typeof(bool));
                    _boolType = boolType; 
                }
                return boolType; 
            } 
        }
 
        /// 
        /// Helper to get and cache the reflection version of a dependency object type array
        /// 
        private static Type[] DpType { 
            get {
                Type[] dpType = _dpType; 
                if (dpType == null) { 
                    dpType = new Type[] { TypeDescriptor.GetReflectionType(typeof(DependencyObject)) };
                    _dpType = dpType; 
                }

                return dpType;
            } 
        }
 
        #endregion 

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

        #region Private Fields 
 
        private static Binder _dpBinder = new AttachedPropertyMethodSelector();
 
        private static object _nullMethodSentinel = new object();

        // Synchronized by "_getMethodCache".  Note these are "reflection"
        // member infos and should only be passed types returned from 
        // GetReflectionType.
        private static Hashtable _getMethodCache = new Hashtable(); 
 
        // Synchronized by "_setMethodCache".  Note these are "reflection"
        // member infos and should only be passed types returned from 
        // GetReflectionType.
        private static Hashtable _setMethodCache = new Hashtable();

        // Synchronization object for Attributes property.  This would be better to be a 
        // member than a static value, but the need for a lock on Attributes is very
        // rare and isn't worth the additional space this would take up as a member 
        private static object _attributeSyncLock = new object(); 

        private PropertyDescriptor _property; 
        private DependencyProperty _dp;
        private Type _componentType;
        private PropertyMetadata _metadata;
        private bool _queriedShouldSerializeMethod; 
        private bool _queriedResetMethod;
        private Dictionary _trackers; 
 
        // These are reflection method infos, and should only be passed types
        // returned from GetReflectionType. 
        private MethodInfo _shouldSerializeMethod;
        private MethodInfo _resetMethod;

        // These are constructed on demand and cleared when our cache is 
        // cleared.  They are all reflection types.
        private static Type[] _dpType; 
        private static Type _boolType; 
        private static Type _attributeType;
        private static Type _attachedPropertyBrowsableType; 

        #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