MetadataStore.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 / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / Base / Core / Metadata / MetadataStore.cs / 1305376 / MetadataStore.cs

                            using System.Diagnostics.CodeAnalysis; 

namespace System.Activities.Presentation.Metadata
{
    using System; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.Reflection;
    using System.Activities.Presentation.Internal.Metadata;
    using System.Runtime;
    using System.Activities.Presentation; 

    ///  
    /// The MetadataStore is a container of custom attribute metadata. 
    /// Custom attributes may be defined in an attribute table and added
    /// to the metadata store.  Once added, these attributes will appear 
    /// in calls made to TypeDescriptor.
    /// 
    public static class MetadataStore {
 
        private static object _syncLock = new object();
        private static MetadataStoreProvider _objectProvider; 
        private static Dictionary _interfaces; 
        private static Hashtable _typeAttributeCache;
 
        [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
        static MetadataStore()
        {
            TypeDescriptor.Refreshed += TypeDescriptor_Refreshed; 
        }
 
        static void TypeDescriptor_Refreshed(RefreshEventArgs e) { 
            _typeAttributeCache = null;
        } 

        /// 
        /// Adds the given table to the current AppDomain�s attribute store.
        /// Once added, calls to TypeDescriptor will use attributes defined 
        /// in the newly added table.  Multiple tables may be added to the
        /// attribute store.  In the case of conflicts, attributes in the 
        /// most recently added table win. 
        /// 
        /// The table to add 
        /// if table is null
        public static void AddAttributeTable(AttributeTable table) {
            if (table == null) throw FxTrace.Exception.ArgumentNull("table");
 
            lock (_syncLock) {
                if (_objectProvider == null) { 
                    _objectProvider = new MetadataStoreProvider(table); 
                    TypeDescriptor.AddProvider(_objectProvider, typeof(object));
                } 
                else {
                    _objectProvider.AddTable(table);
                }
 
                foreach (Type t in table.AttributedTypes) {
 
                    // If there are any interface types in the given 
                    // table, we must add providers specifically for those
                    // types because interfaces do not derive from object and 
                    // are therefore missed by our global hook.

                    if (t.IsInterface) {
                        if (_interfaces == null) { 
                            _interfaces = new Dictionary();
                        } 
                        if (!_interfaces.ContainsKey(t)) { 
                            TypeDescriptor.AddProvider(_objectProvider, t);
                            _interfaces.Add(t, t); 
                        }
                    }
                }
            } 

            // Now invalidate the types. 
            foreach (Type t in table.AttributedTypes) { 
                TypeDescriptor.Refresh(t);
            } 

#if DEBUG
            table.DebugValidateProvider();
#endif 
        }
 
        // 
        // This type description provider is used for all objects and
        // interfaces. 
        //
        private class MetadataStoreProvider : TypeDescriptionProvider {

            private Dictionary _metadataTypeCache; 
            private Dictionary _attributeCache;
            private Dictionary _descriptorCache; 
            private AttributeTable[] _tables; 
            private object _syncLock = new object();
 
            internal MetadataStoreProvider(AttributeTable table)
                : base(TypeDescriptor.GetProvider(typeof(object))) {
                _tables = new AttributeTable[] { table };
            } 

            // 
            // Called by the metadata store to add a new table to our 
            // provider.  Guarded by a lock on the metadata store.
            // 
            internal void AddTable(AttributeTable table) {

                // We don't expect a huge number of tables,
                // so creating a new array here is fine.  Also, 
                // this has the added benefit of allowing code
                // that eumerates tables to be thread-safe 
                // without taking any locks.  Caller is responsible 
                // for ensuring AddTable is synchronized.
 
                AttributeTable[] newTables;
                newTables = new AttributeTable[_tables.Length + 1];
                _tables.CopyTo(newTables, 1);
                newTables[0] = table; 
                _tables = newTables;
 
                if (_attributeCache != null) _attributeCache.Clear(); 

                // Clear all metadata types that will change as 
                // a result of adding this new table

                if (_metadataTypeCache != null) {
                    List toRemove = null; 
                    foreach (Type t in table.AttributedTypes) {
                        foreach (Type cached in _metadataTypeCache.Keys) { 
                            Type realCachedType = cached.UnderlyingSystemType; 
                            if (t.IsAssignableFrom(realCachedType)) {
                                if (toRemove == null) toRemove = new List(); 
                                toRemove.Add(realCachedType);
                            }
                        }
                    } 

                    if (toRemove != null) { 
                        foreach (Type t in toRemove) { 
                            _metadataTypeCache.Remove(t);
                        } 
                    }
                }
            }
 
            //
            // Private helper that creates an attribute collection given an array of attributes. 
            // This does the appropriate pairing down of attributes with matching TypeIds so 
            // the collection contains no redundant attributes.  Attributes should be ordered
            // from most derived to least derived, so the first attribute reported wins. 
            //
            private static AttributeCollection CreateAttributeCollection(Attribute[] attrArray) {
                Dictionary dict = new Dictionary(attrArray.Length);
 
                // Attrs array is ordered by priority, first one in
                // wins. 
 
                int finalCount = attrArray.Length;
 
                for (int idx = 0; idx < attrArray.Length; idx++) {
                    Attribute a = attrArray[idx];
                    if (dict.ContainsKey(a.TypeId)) {
                        attrArray[idx] = null; 
                        finalCount--;
                    } 
                    else { 
                        dict.Add(a.TypeId, a);
                    } 
                }

                Attribute[] finalArray;
 
                if (finalCount != attrArray.Length) {
                    finalArray = new Attribute[finalCount]; 
                    int finalIdx = 0; 
                    for (int idx = 0; idx < attrArray.Length; idx++) {
                        if (attrArray[idx] != null) { 
                            finalArray[finalIdx++] = attrArray[idx];
                        }
                    }
                } 
                else {
                    finalArray = attrArray; 
                } 

                return new AttributeCollection(finalArray); 
            }

            //
            // Returns a cached attribute collection for the given 
            // object type and member.  Member can be null to get
            // attributes for the class. 
            // 
            private AttributeCollection GetAttributes(Type objectType) {
                Fx.Assert(objectType != null, "objectType parameter should not be null"); 
                AttributeCollection attributes;

                // Dictionary does not support thread-safe reads.  We need to lock on
                // all access. 

                lock (_syncLock) { 
                    if (_attributeCache == null) _attributeCache = new Dictionary(); 
                    if (!_attributeCache.TryGetValue(objectType, out attributes)) {
                        attributes = CreateAttributeCollection(GetRawAttributes(objectType, null, null, false)); 
                        _attributeCache[objectType] = attributes;
                    }
                }
 
                return attributes;
            } 
 
            //
            // Raw API to return attributes.  This is used by GetAttributes to 
            // populate the AttributeCollection (which is cached), and by
            // the Attributes property on property and event descriptors (where
            // caching is handled by the Member Descriptor). Attributes
            // are returned from this ordered so the highest priority attributes 
            // are first (first in wins).
            // 
 
            private static Attribute[] GetRawAttributes(Type objectType, string member, MemberDescriptor parentDescriptor, bool isEvent) {
                Fx.Assert(objectType != null, "objectType parameter should not be null"); 
                Type reflectType = TypeDescriptor.GetReflectionType(objectType);

                // There is a bug in CLR reflection that does not respect the "inherit"
                // flag for event or property infos.  Our custom metadata type does respect 
                // this flag and correctly does the right thing.  If the object type we
                // are passed is not a metadata type, just use the default behavior of the 
                // parent member descriptor.  It will be right, and since we're not a metadata 
                // type that means we have no overrides anyway.
                // 
                // The reason we have to call our type with inherit, instead of just using
                // one code path is we need to support the interleaving of CLR and
                // metadata table attributes up the inheritance hierarchy.  MetadataType
                // does that for us. 

                if (parentDescriptor != null && !(reflectType is MetadataType)) { 
                    AttributeCollection attrs = parentDescriptor.Attributes; 
                    Attribute[] attrArray = new Attribute[attrs.Count];
 
                    // CLR property descriptor reverses attribute order.  Fix it.
                    for (int idx = 0; idx < attrArray.Length; idx++) {
                        attrArray[idx] = attrs[attrArray.Length - idx - 1];
                    } 

                    return attrArray; 
                } 

                MemberInfo reflectMember; 
                Type reflectMemberType = null;

                Attribute[] attributes;
 
                if (member == null) {
                    reflectMember = reflectType; 
                } 
                else if (isEvent) {
                    EventInfo info = null; 

                    MemberInfo[] infos = reflectType.GetMember(member, MemberTypes.Event, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
                    if (infos.Length > 0) {
                        info = infos[0] as EventInfo; 
                    }
 
                    reflectMember = info; 
                    if (info != null) reflectMemberType = TypeDescriptor.GetReflectionType(info.EventHandlerType);
                } 
                else {
                    PropertyInfo info = null;

                    MemberInfo[] infos = reflectType.GetMember(member, MemberTypes.Property, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public); 
                    if (infos.Length > 0) {
                        info = infos[0] as PropertyInfo; 
                    } 

                    reflectMember = info; 
                    if (info != null) reflectMemberType = TypeDescriptor.GetReflectionType(info.PropertyType);
                }

                if (reflectMember == null) { 
                    Debug.Fail("Member " + member + " is not a member of type " + objectType.Name);
                    attributes = new Attribute[0]; 
                } 
                else {
                    // Cannot simply cast to Attribute[] 
                    Object[] attrs = reflectMember.GetCustomAttributes(typeof(Attribute), true);
                    List attrList = new List(attrs);

                    Hashtable cache = _typeAttributeCache; 
                    if (cache == null) {
                       cache = new Hashtable(); 
                       _typeAttributeCache = cache; 
                    }
 
                    // Get the base type attributes if we have them
                    if (reflectMemberType != null) {
                        reflectType = reflectMemberType;
 
                        attrs = (object[])cache[reflectType];
                        if (attrs == null) { 
                            attrs = reflectType.GetCustomAttributes(typeof(Attribute), true); 
                            lock (cache.SyncRoot) {
                                cache[reflectType] = attrs; 
                            }
                        }

                        attrList.AddRange(attrs); 
                    }
 
                    // Get interface attributes too. 

                    foreach (Type iface in reflectType.GetInterfaces()) { 
                        attrs = (object[])cache[iface];
                        if (attrs == null) {
                            attrs = iface.GetCustomAttributes(typeof(Attribute), false);
                            lock (cache.SyncRoot) { 
                                cache[iface] = attrs;
                            } 
                        } 

                        attrList.AddRange(attrs); 
                    }

                    // Now go through the attributes and expand those that are
                    // AttributeProviderAttributes 
                    for (int idx = 0; idx < attrList.Count; idx++) {
                        AttributeProviderAttribute a = attrList[idx] as AttributeProviderAttribute; 
                        if (a != null) { 
                            reflectType = Type.GetType(a.TypeName);
                            if (reflectType != null) { 
                                reflectType = TypeDescriptor.GetReflectionType(reflectType);
                                reflectMember = reflectType;

                                if (a.PropertyName != null && a.PropertyName.Length > 0) { 
                                    MemberInfo[] infos = reflectType.GetMember(a.PropertyName);
                                    if (infos != null && infos.Length > 0) { 
                                        reflectMember = infos[0]; 
                                    }
                                } 

                                attrList.AddRange(reflectMember.GetCustomAttributes(typeof(Attribute), true));
                            }
                        } 
                    }
 
                    attributes = new Attribute[attrList.Count]; 

                    for (int idx = 0; idx < attrList.Count; idx++) { 
                        attributes[idx] = (Attribute)attrList[idx];
                    }
                }
 
                return attributes;
            } 
 
            //
            // Access to our descriptor cache 
            //
            private MemberDescriptor GetCachedDescriptor(Type objectType, MemberDescriptor descriptor) {
                MemberDescriptor cached;
                DescriptorKey key = new DescriptorKey(objectType, descriptor); 

                lock (_syncLock) { 
                    if (_descriptorCache == null || !_descriptorCache.TryGetValue(key, out cached)) { 
                        cached = null;
                    } 
                }

                return cached;
            } 

            // 
            // Access to our descriptor cache 
            //
            private void CacheDescriptor(Type objectType, MemberDescriptor descriptor, MemberDescriptor cache) { 

                lock (_syncLock) {
                    if (_descriptorCache == null) {
                        _descriptorCache = new Dictionary(); 
                    }
                    DescriptorKey key = new DescriptorKey(objectType, descriptor); 
 
                    // Caller may ---- and this cache slot may already be allocated.
                    // That's OK; we'll just replace it. 
                    _descriptorCache[key] = cache;
                }
            }
 
            //
            // Takes a collection of events and merges them with our own descriptors. 
            // 
            private EventDescriptorCollection MergeEvents(Type objectType, EventDescriptorCollection incoming) {
                EventDescriptor[] array = new EventDescriptor[incoming.Count]; 
                for (int idx = 0; idx < array.Length; idx++) {
                    EventDescriptor theirs = incoming[idx];
                    EventDescriptor ours = (EventDescriptor)GetCachedDescriptor(objectType, theirs);
                    if (ours == null) { 
                        ours = new MetadataStoreEventDescriptor(objectType, theirs);
                        CacheDescriptor(objectType, theirs, ours); 
                    } 
                    array[idx] = ours;
                } 
                return new EventDescriptorCollection(array, true);
            }

            // 
            // Takes a collection of properties and merges them with our own descriptors.
            // 
            private PropertyDescriptorCollection MergeProperties(Type objectType, PropertyDescriptorCollection incoming) { 
                PropertyDescriptor[] array = new PropertyDescriptor[incoming.Count];
                for (int idx = 0; idx < array.Length; idx++) { 
                    PropertyDescriptor theirs = incoming[idx];
                    PropertyDescriptor ours = (PropertyDescriptor)GetCachedDescriptor(objectType, theirs);
                    if (ours == null) {
                        ours = new MetadataStorePropertyDescriptor(objectType, theirs); 
                        CacheDescriptor(objectType, theirs, ours);
                    } 
                    array[idx] = ours; 
                }
                return new PropertyDescriptorCollection(array, true); 
            }

            //
            // Looks at objectType and returns a wrapped type if needed.  The 
            // parameter may be null, in which case this API returns null.
            // 
            internal Type MergeType(Type objectType) { 
                if (objectType == null) return null;
                return MergeTypeInternal(objectType, null); 
            }

            //
            // Helper method for both MergeType and GetReflectionType 
            //
            private Type MergeTypeInternal(Type objectType, object instance) { 
 
                // If the incoming object type is already one of our wrapped types,
                // there is nothing more for us to do 
                if (objectType is MetadataType) return objectType;

                Type baseReflectionType = base.GetReflectionType(objectType, instance);
                Type reflectionType; 

                lock (_syncLock) { 
                    if (_metadataTypeCache == null || !_metadataTypeCache.TryGetValue(baseReflectionType, out reflectionType)) { 

                        // See if we need to build a custom type for this objectType 

                        bool containsAttributes = false;
                        foreach (AttributeTable table in _tables) {
                            if (table.ContainsAttributes(objectType)) { 
                                containsAttributes = true;
                                break; 
                            } 
                        }
 
                        // If we failed to find attributes quickly, we need
                        // to check base classes and interfaces.

                        if (!containsAttributes) { 
                            foreach (AttributeTable table in _tables) {
                                foreach (Type t in table.AttributedTypes) { 
                                    if (t.IsAssignableFrom(objectType)) { 
                                        containsAttributes = true;
                                        break; 
                                    }
                                }
                            }
                        } 

                        // If we have a table that contains attributes for this type, we need 
                        // to wrap the type in our own reflection type.  If not, we will 
                        // store baseReflectionType in the cache slot.
 
                        if (containsAttributes) {
                            reflectionType = new MetadataType(baseReflectionType, _tables, this);
                        }
                        else { 
                            reflectionType = baseReflectionType;
                        } 
 
                        if (_metadataTypeCache == null) {
                            _metadataTypeCache = new Dictionary(); 
                        }
                        _metadataTypeCache[baseReflectionType] = reflectionType;
                    }
                } 

                return reflectionType; 
            } 

            // 
            // This method is the metadata store's "master hook".  It will return a custom
            // "MetadataType" for all types that have custom metadata declared in the
            // attribute table.  By infusing our custom metadata at this low level,
            // everything that builds on top of reflection can be accomodated. 
            //
            public override Type GetReflectionType(Type objectType, object instance) { 
                if (objectType == null) throw FxTrace.Exception.ArgumentNull("objectType"); 
                return MergeTypeInternal(objectType, instance);
            } 

            //
            // Returns a custom type descriptor for the given object
            // 
            public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) {
                ICustomTypeDescriptor descriptor = base.GetTypeDescriptor(objectType, instance); 
                descriptor = new MetadataStoreTypeDescriptor(this, objectType, descriptor); 
                return descriptor;
            } 

            //
            // A descriptor key is a dictionary key used by
            // our member descriptor cache.  The key consists of a type 
            // and a member descriptor.
            // 
            private struct DescriptorKey : IEquatable { 
                internal readonly Type Type;
                internal readonly MemberDescriptor Member; 

                internal DescriptorKey(Type type, MemberDescriptor member) {
                    Type = type;
                    Member = member; 
                }
 
                public override int GetHashCode() { 
                    int hash = Type.GetHashCode();
                    if (Member != null) { 
                        hash ^= Member.GetHashCode();
                    }
                    return hash;
                } 

                public override bool Equals(object obj) { 
                    return Equals((DescriptorKey)obj); 
                }
 
                public static bool operator ==(DescriptorKey a, DescriptorKey b) {
                    return a.Equals(b);
                }
 
                public static bool operator !=(DescriptorKey a, DescriptorKey b) {
                    return !a.Equals(b); 
                } 

#if DEBUG 
                public override string ToString() {
                    string v = Type.FullName;
                    if (Member != null) v = string.Concat(v, ".", Member);
                    return v; 
                }
#endif 
 
                // IEquatable Members
 
                public bool Equals(DescriptorKey other) {
                    if (Type != other.Type) return false;
                    return object.ReferenceEquals(Member, other.Member);
                } 

            } 
 
            //
            // This type descriptor is what provides additional metadata. 
            // We implement ICustomTypeDescriptor ourselves, rather than
            // derive from the helper CustomTypeDescriptor class because
            // we want this implementation to be built on a struct for
            // performance reasons. 
            //
            private struct MetadataStoreTypeDescriptor : ICustomTypeDescriptor { 
 
                private MetadataStoreProvider _provider;
                private Type _objectType; 
                private ICustomTypeDescriptor _parent;

                internal MetadataStoreTypeDescriptor(MetadataStoreProvider provider, Type objectType, ICustomTypeDescriptor parent) {
                    _provider = provider; 
                    _objectType = objectType;
                    _parent = parent; 
                } 

                        // ICustomTypeDescriptor Members 

                // Calls that just forward the the parent API
                string ICustomTypeDescriptor.GetClassName() { return _parent.GetClassName(); }
                string ICustomTypeDescriptor.GetComponentName() { return _parent.GetComponentName(); } 
                TypeConverter ICustomTypeDescriptor.GetConverter() { return _parent.GetConverter(); }
                EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() { return _parent.GetDefaultEvent(); } 
                PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() { return _parent.GetDefaultProperty(); } 
                object ICustomTypeDescriptor.GetEditor(Type editorBaseType) { return _parent.GetEditor(editorBaseType); }
                object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { return _parent.GetPropertyOwner(pd); } 

                //
                // Override to provide merged metadata
                // 
                AttributeCollection ICustomTypeDescriptor.GetAttributes() {
                    return _provider.GetAttributes(_objectType); 
                } 

                // 
                // Override to provide merged metadata
                //
                EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) {
                    return _provider.MergeEvents(_objectType, _parent.GetEvents(attributes)); 
                }
 
                // 
                // Override to provide merged metadata
                // 
                EventDescriptorCollection ICustomTypeDescriptor.GetEvents() {
                    return _provider.MergeEvents(_objectType, _parent.GetEvents());
                }
 
                //
                // Override to provide merged metadata 
                // 
                PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) {
                    return _provider.MergeProperties(_objectType, _parent.GetProperties(attributes)); 
                }

                //
                // Override to provide merged metadata 
                //
                PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { 
                    return _provider.MergeProperties(_objectType, _parent.GetProperties()); 
                }
 
            }

            //
            // A property descriptor that adds additional metadata to an existing 
            // property descriptor.
            // 
            private class MetadataStorePropertyDescriptor : PropertyDescriptor { 

                private static readonly object _noValue = new object(); 
                private static readonly object _invalidValue = new object();

                private Type _objectType;
                private PropertyDescriptor _parent; 
                private AttributeCollection _attributes;
                private Attribute[] _rawAttributes; 
                private object _defaultValue = _invalidValue; 
                private object _ambientValue = _invalidValue;
 
                // There are simpler base ctors we can invoke that do attribute merging for us.  However,
                // they do it all up front instead of deferring.  We want to defer until someone actually
                // asks for attributes.
                internal MetadataStorePropertyDescriptor(Type objectType, PropertyDescriptor parent) 
                    : base(parent.Name, null) {
                    _objectType = objectType; 
                    _parent = parent; 
                }
 
                //
                // Return our attribute collection.  We cache it
                // for speed.
                // 
                public override AttributeCollection Attributes {
                    get { 
                        CheckAttributesValid(); 
                        if (_attributes == null) {
                            _attributes = MetadataStoreProvider.CreateAttributeCollection(_rawAttributes); 
                        }

                        return _attributes;
                    } 
                }
 
                // 
                // DefaultValue and AmbientValue are two values that are used by
                // ReflectTypeDescriptionProvider in ResetValue(), CanResetValue(), 
                // and ShouldSerializeValue() in such a way that by-passes any additional
                // values provided by the MetadataStore.  As such, we manually look up
                // these two attributes ourselves to keep the MetadataStore functionality
                // intact. 
                //
                private object DefaultValue { 
                    get { 
                        if (_defaultValue == _invalidValue) {
                            DefaultValueAttribute dva = (DefaultValueAttribute) Attributes[typeof(DefaultValueAttribute)]; 
                            if (dva != null) {
                                _defaultValue = dva.Value;
                            }
                            else { 
                                _defaultValue = _noValue;
                            } 
                        } 
                        return _defaultValue;
                    } 
                }

                //
                // See comment for DefaultValue 
                //
                private object AmbientValue { 
                    get { 
                        if (_ambientValue == _invalidValue) {
                            AmbientValueAttribute ava = (AmbientValueAttribute)Attributes[typeof(AmbientValueAttribute)]; 
                            if (ava != null) {
                                _ambientValue = ava.Value;
                            }
                            else { 
                                _ambientValue = _noValue;
                            } 
                        } 
                        return _ambientValue;
                    } 
                }

                //
                // This is a little strange and merits some explanation. 
                // We want to cache our attribute collection, but we need
                // to know when to invalidate the cache. MemberDescriptor 
                // has an internal version stamp that it compares with 
                // TypeDescriptor's metadata version and automatically invalidates
                // its own cached values for attributes.  The trick is 
                // we need to know when MemberDescriptor invalidated its
                // cached values.  We do this by keying off the fact that
                // MemberDescriptor will call FillAttributes when its cache
                // needs to be repopulated.  But, in oder to get MemberDescriptor 
                // to look at its cache we must access an API that requires
                // cached data.  AttributeArray does this in the lightest 
                // possible way.  The actual set of attributes in the array 
                // is always an empty set, but we don't care; we only need
                // to access the property.  The return value of the API 
                // and the check for length are only here so the compiler
                // and FXCop do not complain about us calling a property
                // and not using the return value.  The attribute array
                // always contains zero elements. 
                //
                private bool CheckAttributesValid() { 
                    Fx.Assert(AttributeArray.Length == 0, "Attribute array should always contain zero elements"); 
                    return AttributeArray.Length == 0 && _attributes != null;
                } 

                //
                // This method is called when we need to populate the raw set of
                // attributes for this property. 
                //
                protected override void FillAttributes(IList attributeList) { 
                    _attributes = null; 
                    _defaultValue = _invalidValue;
                    _ambientValue = _invalidValue; 

                    _rawAttributes = MetadataStoreProvider.GetRawAttributes(_objectType, Name, _parent, false);
                    base.FillAttributes(attributeList);
                } 

                // PropertyDescriptor API. 
                public override bool CanResetValue(object component) { 
                    if (DefaultValue != _noValue) {
                        object currentValue = GetValue(component); 
                        return !object.Equals(currentValue, DefaultValue);
                    }
                    else if (AmbientValue != _noValue) {
                        object currentValue = GetValue(component); 
                        return !object.Equals(currentValue, AmbientValue);
                    } 
                    else { 
                        return _parent.CanResetValue(component);
                    } 
                }

                public override void ResetValue(object component) {
                    if (DefaultValue != _noValue) { 
                        SetValue(component, DefaultValue);
                    } 
                    else if (AmbientValue != _noValue) { 
                        SetValue(component, AmbientValue);
                    } 
                    else {
                        _parent.ResetValue(component);
                    }
                } 

                public override bool ShouldSerializeValue(object component) { 
                    if (DefaultValue != _noValue) { 
                        object currentValue = GetValue(component);
                        return !object.Equals(currentValue, DefaultValue); 
                    }
                    else if (AmbientValue != _noValue) {
                        object currentValue = GetValue(component);
                        return !object.Equals(currentValue, AmbientValue); 
                    }
                    else { 
                        return _parent.ShouldSerializeValue(component); 
                    }
                } 

                public override void AddValueChanged(object component, EventHandler handler) { _parent.AddValueChanged(component, handler); }
                public override Type ComponentType { get { return _parent.ComponentType; } }
                [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Propagating the error might cause VS to crash")] 
                [SuppressMessage("Reliability", "Reliability108", Justification = "Propagating the error might cause VS to crash")]
                public override object GetValue(object component) 
                { 
                    object retValue = null;
 
                    try
                    {
                        retValue = _parent.GetValue(component);
                    } 
                    catch (System.Exception)
                    { 
                        // GetValue throws an exception if Value is not available 
                    }
 
                    return retValue;
                }
                public override bool IsReadOnly { get { return _parent.IsReadOnly || Attributes.Contains(ReadOnlyAttribute.Yes); } }
                public override Type PropertyType { get { return _parent.PropertyType; } } 
                public override void SetValue(object component, object value) { _parent.SetValue(component, value); }
                public override void RemoveValueChanged(object component, EventHandler handler) { _parent.RemoveValueChanged(component, handler); } 
                public override bool SupportsChangeEvents { get { return _parent.SupportsChangeEvents; } } 
            }
 
            //
            // An event descriptor that adds additional metadata to an existing
            // event descriptor.
            // 
            private class MetadataStoreEventDescriptor : EventDescriptor {
                private Type _objectType; 
                private EventDescriptor _parent; 

                // There are simpler base ctors we can invoke that do attribute merging for us.  However, 
                // they do it all up front instead of deferring.  We want to defer until someone actually
                // asks for attributes.
                internal MetadataStoreEventDescriptor(Type objectType, EventDescriptor parent)
                    : base(parent.Name, null) { 
                    _objectType = objectType;
                    _parent = parent; 
                } 

                // 
                // We override this so we can merge in our additional attributes.
                // By overriding here, we wait until someone actually asks for
                // attributes before merging.
                // 
                protected override AttributeCollection CreateAttributeCollection() {
                    Attribute[] attrs = MetadataStoreProvider.GetRawAttributes(_objectType, Name, _parent, true); 
 
                    // We must let MemberDescriptor build its attributes, even if we're going
                    // to replace them.  The reason for this is that MemberDescriptor keeps an 
                    // internal version stamp.  This version stamp changes when someone adds
                    // a new TypeDescriptionProvider.  If we don't let MemberDescriptor maintain
                    // this version stamp it won't invalidate metadata when someone adds or removes
                    // a TypeDescriptionProvider, which can cause us to return stale data. 

                    AttributeArray = attrs; 
                    AttributeCollection attributes = base.CreateAttributeCollection(); // do not delete this 
                    attributes = MetadataStoreProvider.CreateAttributeCollection(attrs);
                    return attributes; 
                }

                // EventDescriptor API
                public override void AddEventHandler(object component, Delegate value) { _parent.AddEventHandler(component, value); } 
                public override Type ComponentType { get { return _parent.ComponentType; } }
                public override Type EventType { get { return _parent.EventType; } } 
                public override bool IsMulticast { get { return _parent.IsMulticast; } } 
                public override void RemoveEventHandler(object component, Delegate value) { _parent.RemoveEventHandler(component, value); }
            } 
        }

        //
        // This type is the core of our metadata store.  We offer this through our type 
        // description provider as the "reflection type" that should be used during
        // reflection operations.  All things within TypeDescriptor will use this 
        // type to get metadata, which gives us a big hook into their mechanism. 
        // By hooking at this low level we can be sure to cover all of our bases.
        // 
        private class MetadataType : Type {

            private Type _baseReflectionType;
            private AttributeTable[] _tables; 
            private MetadataStoreProvider _provider;
            private Dictionary _memberCache; 
            private Hashtable _seenAttributes; 
            private AttributeMergeCache _cache;
            private object _syncLock = new object(); 

            internal MetadataType(Type baseReflectionType, AttributeTable[] tables, MetadataStoreProvider provider) {
                _baseReflectionType = baseReflectionType;
                _tables = tables; 
                _provider = provider;
            } 
 
            // Type Forward APIs
            // 
            // The majority of Type's API is just forwarded to our base reflection
            // type.
            //
            public override Guid GUID { get { return _baseReflectionType.GUID; } } 
            public override Assembly Assembly { get { return _baseReflectionType.Assembly; } }
            public override string AssemblyQualifiedName { get { return _baseReflectionType.AssemblyQualifiedName; } } 
            public override bool ContainsGenericParameters { get { return _baseReflectionType.ContainsGenericParameters; } } 
            public override MethodBase DeclaringMethod { get { return _baseReflectionType.DeclaringMethod; } }
            public override RuntimeTypeHandle TypeHandle { get { return _baseReflectionType.TypeHandle; } } 
            public override int GetHashCode() { return _baseReflectionType.GetHashCode(); }
            public override string FullName { get { return _baseReflectionType.FullName; } }
            public override GenericParameterAttributes GenericParameterAttributes { get { return _baseReflectionType.GenericParameterAttributes; } }
            public override int GenericParameterPosition { get { return _baseReflectionType.GenericParameterPosition; } } 
            public override int GetArrayRank() { return _baseReflectionType.GetArrayRank(); }
            protected override TypeAttributes GetAttributeFlagsImpl() { return _baseReflectionType.Attributes; } 
            protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { return _baseReflectionType.GetConstructor(bindingAttr, binder, callConvention, types, modifiers); } 
            public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) { return _baseReflectionType.GetConstructors(bindingAttr); }
            public override FieldInfo GetField(string name, BindingFlags bindingAttr) { return _baseReflectionType.GetField(name, bindingAttr); } 
            public override FieldInfo[] GetFields(BindingFlags bindingAttr) { return _baseReflectionType.GetFields(bindingAttr); }
            protected override bool HasElementTypeImpl() { return _baseReflectionType.HasElementType; }
            public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) { return _baseReflectionType.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters); }
            protected override bool IsArrayImpl() { return _baseReflectionType.IsArray; } 
            protected override bool IsByRefImpl() { return _baseReflectionType.IsByRef; }
            protected override bool IsCOMObjectImpl() { return _baseReflectionType.IsCOMObject; } 
            protected override bool IsPointerImpl() { return _baseReflectionType.IsPointer; } 
            protected override bool IsPrimitiveImpl() { return _baseReflectionType.IsPrimitive; }
            public override Module Module { get { return _baseReflectionType.Module; } } 
            public override string Namespace { get { return _baseReflectionType.Namespace; } }
            public override Type UnderlyingSystemType { get { return _baseReflectionType.UnderlyingSystemType; } }
            public override string Name { get { return _baseReflectionType.Name; } }
            public override InterfaceMapping GetInterfaceMap(Type interfaceType) { return _baseReflectionType.GetInterfaceMap(interfaceType); } 
            public override bool IsAssignableFrom(Type c) { return _baseReflectionType.IsAssignableFrom(c); }
            protected override bool IsContextfulImpl() { return _baseReflectionType.IsContextful; } 
            public override bool IsGenericParameter { get { return _baseReflectionType.IsGenericParameter; } } 
            public override bool IsGenericType { get { return _baseReflectionType.IsGenericType; } }
            public override bool IsGenericTypeDefinition { get { return _baseReflectionType.IsGenericTypeDefinition; } } 
            public override bool IsInstanceOfType(object o) { return _baseReflectionType.IsInstanceOfType(o); }
            protected override bool IsMarshalByRefImpl() { return _baseReflectionType.IsMarshalByRef; }
            public override bool IsSubclassOf(Type c) { return _baseReflectionType.IsSubclassOf(c); }
            protected override bool IsValueTypeImpl() { return _baseReflectionType.IsValueType; } 
            public override Type MakeArrayType() { return _baseReflectionType.MakeArrayType(); }
            public override Type MakeArrayType(int rank) { return _baseReflectionType.MakeArrayType(rank); } 
            public override Type MakeByRefType() { return _baseReflectionType.MakeByRefType(); } 
            public override Type MakeGenericType(params Type[] typeArguments) { return _baseReflectionType.MakeGenericType(typeArguments); }
            public override Type MakePointerType() { return _baseReflectionType.MakePointerType(); } 
            public override MemberTypes MemberType { get { return _baseReflectionType.MemberType; } }
            public override int MetadataToken { get { return _baseReflectionType.MetadataToken; } }
            public override Type ReflectedType { get { return _baseReflectionType.ReflectedType; } }
            public override System.Runtime.InteropServices.StructLayoutAttribute StructLayoutAttribute { get { return _baseReflectionType.StructLayoutAttribute; } } 
            public override string ToString() { return _baseReflectionType.ToString(); }
 
 
            // Type APIs
 
            //
            // Wrap returned types
            //
            public override Type GetElementType() { 
                return _provider.MergeType(_baseReflectionType.GetElementType());
            } 
 
            //
            // Wrap returned types 
            //
            public override Type DeclaringType {
                get { return _provider.MergeType(_baseReflectionType.DeclaringType); }
            } 

            // 
            // Wrap returned types 
            //
            public override Type[] FindInterfaces(TypeFilter filter, object filterCriteria) { 
                Type[] ifaces = _baseReflectionType.FindInterfaces(filter, filterCriteria);
                for (int idx = 0; idx < ifaces.Length; idx++) {
                    ifaces[idx] = _provider.MergeType(ifaces[idx]);
                } 
                return ifaces;
            } 
 
            //
            // Wrap returned types 
            //
            public override Type BaseType {
                get { return _provider.MergeType(_baseReflectionType.BaseType); }
            } 

            // 
            // Wrap returned types 
            //
            public override Type GetInterface(string name, bool ignoreCase) { 
                return _provider.MergeType(_baseReflectionType.GetInterface(name, ignoreCase));
            }

            // 
            // Wrap returned types
            // 
            public override Type[] GetInterfaces() { 
                Type[] ifaces = _baseReflectionType.GetInterfaces();
                for (int idx = 0; idx < ifaces.Length; idx++) { 
                    ifaces[idx] = _provider.MergeType(ifaces[idx]);
                }
                return ifaces;
            } 

            // 
            // Wrap returned types 
            //
            public override Type GetNestedType(string name, BindingFlags bindingAttr) { 
                return _provider.MergeType(_baseReflectionType.GetNestedType(name, bindingAttr));
            }

            // 
            // Wrap returned types
            // 
            public override Type[] GetNestedTypes(BindingFlags bindingAttr) { 
                Type[] ifaces = _baseReflectionType.GetNestedTypes(bindingAttr);
                for (int idx = 0; idx < ifaces.Length; idx++) { 
                    ifaces[idx] = _provider.MergeType(ifaces[idx]);
                }
                return ifaces;
            } 

            // 
            // Wrap returned types 
            //
            public override Type[] GetGenericArguments() { 
                Type[] ifaces = _baseReflectionType.GetGenericArguments();
                for (int idx = 0; idx < ifaces.Length; idx++) {
                    ifaces[idx] = _provider.MergeType(ifaces[idx]);
                } 
                return ifaces;
            } 
 
            //
            // Wrap returned types 
            //
            public override Type[] GetGenericParameterConstraints() {
                Type[] ifaces = _baseReflectionType.GetGenericParameterConstraints();
                for (int idx = 0; idx < ifaces.Length; idx++) { 
                    ifaces[idx] = _provider.MergeType(ifaces[idx]);
                } 
                return ifaces; 
            }
 
            //
            // Wrap returned types
            //
            public override Type GetGenericTypeDefinition() { 
                return _provider.MergeType(_baseReflectionType.GetGenericTypeDefinition());
            } 
 
            //
            // Custom attribute access 
            //
            public override object[] GetCustomAttributes(bool inherit) {
                return MergeAttributes(null, _baseReflectionType, inherit, ref _cache);
            } 

            // 
            // Custom attribute access 
            //
            public override object[] GetCustomAttributes(Type attributeType, bool inherit) { 
                return MergeAttributes(attributeType, _baseReflectionType, inherit, ref _cache);
            }

            // 
            // Custom attribute access
            // 
            public override bool IsDefined(Type attributeType, bool inherit) { 
                bool isDefined = _baseReflectionType.IsDefined(attributeType, inherit);
                if (!isDefined) isDefined = IsDefinedInTable(attributeType, null, inherit); 
                return isDefined;
            }

            // 
            // Member access
            // 
            public override MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria) { 
                MemberInfo[] infos = _baseReflectionType.FindMembers(memberType, bindingAttr, filter, filterCriteria);
                return MergeMembers(infos); 
            }

            //
            // Member access 
            //
            public override MemberInfo[] GetDefaultMembers() { 
                MemberInfo[] infos = _baseReflectionType.GetDefaultMembers(); 
                return MergeMembers(infos);
            } 

            //
            // Member access
            // 
            public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) {
                MemberInfo[] infos = _baseReflectionType.GetMember(name, type, bindingAttr); 
                return MergeMembers(infos); 
            }
 
            //
            // Member access
            //
            public override MemberInfo[] GetMember(string name, BindingFlags bindingAttr) { 
                MemberInfo[] infos = _baseReflectionType.GetMember(name, bindingAttr);
                return MergeMembers(infos); 
            } 

            // 
            // Member access
            //
            public override MemberInfo[] GetMembers(BindingFlags bindingAttr) {
                MemberInfo[] infos = _baseReflectionType.GetMembers(bindingAttr); 
                return MergeMembers(infos);
            } 
 
            //
            // Event access 
            //
            public override EventInfo GetEvent(string name, BindingFlags bindingAttr) {
                EventInfo info = _baseReflectionType.GetEvent(name, bindingAttr);
                return MergeEvent(info); 
            }
 
            // 
            // Event access
            // 
            public override EventInfo[] GetEvents() {
                EventInfo[] infos = _baseReflectionType.GetEvents();
                return MergeEvents(infos);
            } 

            // 
            // Event access 
            //
            public override EventInfo[] GetEvents(BindingFlags bindingAttr) { 
                EventInfo[] infos = _baseReflectionType.GetEvents(bindingAttr);
                return MergeEvents(infos);
            }
 
            //
            // Method access 
            // 
            protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) {
                MethodInfo info; 

                if (types == null) {
                    info = _baseReflectionType.GetMethod(name, bindingAttr);
                } 
                else {
                    info = _baseReflectionType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers); 
                } 

                if (info != null) { 
                    info = MergeMethod(info);
                }

                return info; 
            }
 
            // 
            // Method access
            // 
            public override MethodInfo[] GetMethods(BindingFlags bindingAttr) {
                MethodInfo[] infos = _baseReflectionType.GetMethods(bindingAttr);
                return MergeMethods(infos);
            } 

            // 
            // Property access 
            //
            public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { 
                PropertyInfo[] infos = _baseReflectionType.GetProperties(bindingAttr);
                return MergeProperties(infos);
            }
 
            //
            // Property access 
            // 
            protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) {
                PropertyInfo info; 
                if (types != null) {
                    info = _baseReflectionType.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
                }
                else { 
                    info = _baseReflectionType.GetProperty(name, bindingAttr);
                } 
 
                return MergeProperty(info);
            } 


            // Merging APIs
 
            //
            // Returns true if the given attribute type is defined in any attribute table. 
            // This can take null for the member, in which case it searches type attributes. 
            // Table is assigned at construction and read-only, so no locking required.
            // 
            private bool IsDefinedInTable(Type attributeType, MemberInfo member, bool inherit) {
                bool isDefined = false;
                for (Type t = UnderlyingSystemType; t != null && !isDefined; t = t.BaseType) {
                    foreach (AttributeTable table in _tables) { 
                        IEnumerable attrEnum;
                        if (member == null) { 
                            attrEnum = table.GetCustomAttributes(t); 
                        }
                        else { 
                            attrEnum = table.GetCustomAttributes(t, member);
                        }

                        foreach (object a in attrEnum) { 
                            if (attributeType.IsInstanceOfType(a)) {
                                isDefined = true; 
                                break; 
                            }
                        } 

                        if (isDefined) break;
                    }
 
                    if (!inherit) break;
                } 
                return isDefined; 
            }
 
            //
            // Merging of an array of attributes.  This is called from
            // GetCustomAttributes for both types and members.  Attributes
            // must be merged so the most derived and highest priority 
            // attributes are first in the list.  Metadata store attributes
            // always take higher precidence than CLR attributes. 
            // 
            [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
            private object[] MergeAttributes(Type filterType, MemberInfo member, bool inherit, ref AttributeMergeCache cache) { 

                Type currentType = UnderlyingSystemType;
                MemberInfo currentMember = member;
 
                if (cache == null) cache = new AttributeMergeCache();
                if (cache.FilterType != filterType || 
                    cache.Member != member || 
                    cache.Inherit != inherit) {
 
                    cache.FilterType = filterType;
                    cache.Member = member;
                    cache.Inherit = inherit;
                    if (cache.Cache != null) cache.Cache.Clear(); 
                }
                else if (cache.Cache != null) { 
                    // Cache is valid; return it 
                    return (object[])cache.Cache.ToArray(filterType ?? typeof(object));
                } 


                // Cache is invalid or null.  Walk attributes.
 
                if (cache.Cache == null) cache.Cache = new ArrayList();
                ArrayList compiledAttributes = cache.Cache; 
 
                lock (_syncLock) {
 
                    if (_seenAttributes == null) {
                        _seenAttributes = new Hashtable();
                    }
                    else { 
                        _seenAttributes.Clear();
                    } 
 
                    bool firstIteration = true;
                    bool isType = member is Type; 
                    bool includeClrAttributes = (isType || currentMember.DeclaringType == currentType);

                    while (currentType != null && currentMember != null) {
 
                        foreach (object attr in MergeAttributesIterator(currentType, currentMember, includeClrAttributes)) {
 
                            if (filterType != null && !filterType.IsAssignableFrom(attr.GetType())) 
                                continue;
 
                            AttributeData attrData = AttributeDataCache.GetAttributeData(attr.GetType());
                            bool haveSeenBefore = _seenAttributes.ContainsKey(attrData.AttributeType);

                            // Can we have more than one? 
                            if (haveSeenBefore &&
                                !attrData.AllowsMultiple) 
                                continue; 

                            // Is this attribute inheritable? 
                            if (!firstIteration &&
                                !attrData.IsInheritable)
                                continue;
 
                            // We do a scan here for TypeDescriptionProviderAttribute.  Because we
                            // are creating a custom type here and gathering metadata from 
                            // our base type, it is very important that we don't offer this attribute. 
                            // Doing so could cause TypeDescriptor to add a provider for this type
                            // and create a cycle 
                            if (attrData.AttributeType.Equals(typeof(TypeDescriptionProviderAttribute)))
                                continue;

                            compiledAttributes.Add(attr); 
                            _seenAttributes[attrData.AttributeType] = attr;
                        } 
 
                        // Continue?
                        if (!inherit) 
                            break;

                        // Advance up the type hierarchy
                        // 
                        // Note: CLR attributes key off of currentMember.  MetadataStore attributes key
                        // off of currentType and memberName.  Because we advance currentType independent of 
                        // currentMember, it is possible for the currentMember to belong to some 
                        // ancestor of currentType.  As such, we wait with advancing currentMember until
                        // currentType catches up.  While we wait, we do not include the CLR attributes in 
                        // the mix because they would be added multiple times as a result.

                        // Is currentType caught up to currentMember.DeclaringType?
                        if (isType || currentMember.DeclaringType == currentType) { 
                            currentMember = AttributeDataCache.GetBaseMemberInfo(currentMember);
                        } 
 
                        currentType = currentType.BaseType;
 
                        if (isType || currentMember == null || currentMember.DeclaringType == currentType) {
                            includeClrAttributes = true;
                        }
                        else { 
                            includeClrAttributes = false;
                        } 
 
                        firstIteration = false;
                    } 
                }

                return (object[])compiledAttributes.ToArray(filterType ?? typeof(object));
            } 

            // 
            // Enumerates through values contained in the attribute cache in 
            // an order that returns the MetadataStore attributes before returning
            // the CLR attributes (if requested) 
            //
            private IEnumerable MergeAttributesIterator(Type type, MemberInfo member, bool includeClrAttributes) {
                // MetadataStore uses member name string, instead of MemberInfo to store custom attributes,
                // so figure out what the member name is.  For types, it will be null. 
                string memberName = GetMemberName(member);
 
                // Go through the MetadataStore attributes first, as they take precedence over CLR attributes 
                foreach (object attr in AttributeDataCache.GetMetadataStoreAttributes(type, memberName, _tables))
                    yield return attr; 

                if (includeClrAttributes) {
                    // Go through the CLR attributes second
                    foreach (object attr in AttributeDataCache.GetClrAttributes(member)) 
                        yield return attr;
                } 
            } 

            // 
            // Gets the member name from the specified MemberInfo that we use as key
            // to get custom attributes from the MetadataStore.  Types will return null.
            //
            private static string GetMemberName(MemberInfo member) { 
                if (member is Type)
                    return null; 
 
                // The only methods supported in metadata store are those related to
                // Get methods for DependencyProperties and they start with a "Get..." 
                if (member.MemberType == MemberTypes.Method) {
                    Fx.Assert(
                        member.Name.StartsWith("Get", StringComparison.Ordinal) &&
                        member.Name.Length > 3, 
                        "MetadataStore expects to only see Get[Foo] or Set[Foo] MethodInfos");
 
                    return member.Name.Substring(3); 
                }
 
                return member.Name;
            }

            // 
            // Merging of an event.
            // 
            private EventInfo MergeEvent(EventInfo info) { 
                if (info == null) return null;
 
                MemberInfo cache;

                lock (_syncLock) {
                    if (_memberCache == null || !_memberCache.TryGetValue(info, out cache)) { 

                        if (_memberCache == null) { 
                            _memberCache = new Dictionary(); 
                        }
 
                        EventInfo newInfo = new MetadataEventInfo(info, this);
                        _memberCache[info] = newInfo;
                        info = newInfo;
                    } 
                    else {
                        info = (EventInfo)cache; 
                    } 
                }
 
                return info;
            }

            // 
            // Merging of an array of events.
            // 
            private EventInfo[] MergeEvents(EventInfo[] infos) { 
                for (int idx = 0; idx < infos.Length; idx++) {
                    infos[idx] = MergeEvent(infos[idx]); 
                }
                return infos;
            }
 
            //
            // Merging a generic member calls down to specific 
            // merge functions based on the type of the member. 
            //
            private MemberInfo MergeMember(MemberInfo info) { 
                MethodInfo m;
                PropertyInfo p;
                EventInfo e;
 
                if ((m = info as MethodInfo) != null) {
                    return MergeMethod(m); 
                } 
                else if ((p = info as PropertyInfo) != null) {
                    return MergeProperty(p); 
                }
                else if ((e = info as EventInfo) != null) {
                    return MergeEvent(e);
                } 

                return info; 
            } 

            // 
            // Merging a generic member calls down to specific
            // merge functions based on the type of the member.
            //
            private MemberInfo[] MergeMembers(MemberInfo[] infos) { 
                for (int idx = 0; idx < infos.Length; idx++) {
                    infos[idx] = MergeMember(infos[idx]); 
                } 
                return infos;
            } 

            //
            // Merging of a method.  We only deal with
            // static methods in the format Get 
            // so we can support attached properties.  Otherwise,
            // we let the method be. 
            // 
            private MethodInfo MergeMethod(MethodInfo info) {
                if (info == null) return null; 

                if (info.IsStatic && info.Name.StartsWith("Get", StringComparison.Ordinal)) {
                    MemberInfo cache;
 
                    lock (_syncLock) {
                        if (_memberCache == null || !_memberCache.TryGetValue(info, out cache)) { 
 
                            if (_memberCache == null) {
                                _memberCache = new Dictionary(); 
                            }

                            MethodInfo newInfo = new MetadataMethodInfo(info, this);
                            _memberCache[info] = newInfo; 
                            info = newInfo;
                        } 
                        else { 
                            info = (MethodInfo)cache;
                        } 
                    }
                }
                return info;
            } 

            // 
            // Merging of an array of methods. 
            //
            private MethodInfo[] MergeMethods(MethodInfo[] infos) { 
                for (int idx = 0; idx < infos.Length; idx++) {
                    infos[idx] = MergeMethod(infos[idx]);
                }
                return infos; 
            }
 
            // 
            // Merging of a property.
            // 
            private PropertyInfo MergeProperty(PropertyInfo info) {
                if (info == null) return null;

                MemberInfo cache; 

                lock (_syncLock) { 
                    if (_memberCache == null || !_memberCache.TryGetValue(info, out cache)) { 

                        if (_memberCache == null) { 
                            _memberCache = new Dictionary();
                        }

                        PropertyInfo newInfo = new MetadataPropertyInfo(info, this); 
                        _memberCache[info] = newInfo;
                        info = newInfo; 
                    } 
                    else {
                        info = (PropertyInfo)cache; 
                    }
                }

                return info; 
            }
 
            // 
            // Merging of an array of properties.
            // 
            private PropertyInfo[] MergeProperties(PropertyInfo[] infos) {
                for (int idx = 0; idx < infos.Length; idx++) {
                    infos[idx] = MergeProperty(infos[idx]);
                } 
                return infos;
            } 
 

            // 
            // A simple class that holds merged attribute data.
            //
            private class AttributeMergeCache {
                internal Type FilterType; 
                internal bool Inherit;
                internal ArrayList Cache; 
                internal MemberInfo Member; 
            }
 
            //
            // A property info that contains our custom metadata.
            //
            private class MetadataPropertyInfo : PropertyInfo { 

                private PropertyInfo _info; 
                private MetadataType _type; 
                private AttributeMergeCache _cache;
 
                internal MetadataPropertyInfo(PropertyInfo info, MetadataType type) {
                    _info = info;
                    _type = type;
                } 

                // 
                // PropertyInfo overrides 
                //
                public override PropertyAttributes Attributes { get { return _info.Attributes; } } 
                public override bool CanRead { get { return _info.CanRead; } }
                public override bool CanWrite { get { return _info.CanWrite; } }
                public override MethodInfo[] GetAccessors(bool nonPublic) { return _info.GetAccessors(nonPublic); }
                public override MethodInfo GetGetMethod(bool nonPublic) { return _info.GetGetMethod(nonPublic); } 
                public override ParameterInfo[] GetIndexParameters() { return _info.GetIndexParameters(); }
                public override MethodInfo GetSetMethod(bool nonPublic) { return _info.GetSetMethod(nonPublic); } 
                public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { return _info.GetValue(obj, invokeAttr, binder, index, culture); } 
                public override Type PropertyType { get { return _info.PropertyType; } }
                public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { _info.SetValue(obj, value, invokeAttr, binder, index, culture); } 
                public override Type DeclaringType { get { return _info.DeclaringType; } }
                public override string Name { get { return _info.Name; } }
                public override Type ReflectedType { get { return _info.ReflectedType; } }
                public override bool Equals(object obj) { return object.ReferenceEquals(this, obj); } 
                public override int GetHashCode() { return _info.GetHashCode(); }
                public override object GetConstantValue() { return _info.GetConstantValue(); } 
                public override Type[] GetOptionalCustomModifiers() { return _info.GetOptionalCustomModifiers(); } 
                public override object GetRawConstantValue() { return _info.GetRawConstantValue(); }
                public override Type[] GetRequiredCustomModifiers() { return _info.GetRequiredCustomModifiers(); } 
                public override object GetValue(object obj, object[] index) { return _info.GetValue(obj, index); }
                public override MemberTypes MemberType { get { return _info.MemberType; } }
                public override int MetadataToken { get { return _info.MetadataToken; } }
                public override Module Module { get { return _info.Module; } } 
                public override void SetValue(object obj, object value, object[] index) { _info.SetValue(obj, value, index); }
                public override string ToString() { return _info.ToString(); } 
 
                //
                // Merges our custom attributes in with those of the member info. 
                //
                public override object[] GetCustomAttributes(Type attributeType, bool inherit) {
                    return _type.MergeAttributes(attributeType, _info, inherit, ref _cache);
                } 

                // 
                // Merges our custom attributes in with those of the member info. 
                //
                public override object[] GetCustomAttributes(bool inherit) { 
                    return _type.MergeAttributes(null, _info, inherit, ref _cache);
                }

                // 
                // Determines if an attribute exists in the member info
                // or in our own code. 
                // 
                public override bool IsDefined(Type attributeType, bool inherit) {
                    bool isDefined = _info.IsDefined(attributeType, inherit); 
                    if (!isDefined) isDefined = _type.IsDefinedInTable(attributeType, _info, inherit);
                    return isDefined;
                }
            } 

            // 
            // An EventInfo that provides our custom attributes. 
            //
            private class MetadataEventInfo : EventInfo { 

                private EventInfo _info;
                private MetadataType _type;
                private AttributeMergeCache _cache; 

                internal MetadataEventInfo(EventInfo info, MetadataType type) { 
                    _info = info; 
                    _type = type;
                } 

                //
                // EventInfo overrides
                // 
                public override EventAttributes Attributes { get { return _info.Attributes; } }
                public override string Name { get { return _info.Name; } } 
                public override Type ReflectedType { get { return _info.ReflectedType; } } 
                public override bool Equals(object obj) { return object.ReferenceEquals(this, obj); }
                public override int GetHashCode() { return _info.GetHashCode(); } 
                public override MethodInfo[] GetOtherMethods(bool nonPublic) { return _info.GetOtherMethods(nonPublic); }
                public override MemberTypes MemberType { get { return _info.MemberType; } }
                public override int MetadataToken { get { return _info.MetadataToken; } }
                public override Module Module { get { return _info.Module; } } 
                public override string ToString() { return _info.ToString(); }
                public override MethodInfo GetAddMethod(bool nonPublic) { return _info.GetAddMethod(nonPublic); } 
                public override MethodInfo GetRaiseMethod(bool nonPublic) { return _info.GetRaiseMethod(nonPublic); } 
                public override MethodInfo GetRemoveMethod(bool nonPublic) { return _info.GetRemoveMethod(nonPublic); }
                public override Type DeclaringType { get { return _info.DeclaringType; } } 

                //
                // Merges our custom attributes in with those of the member info.
                // 
                public override object[] GetCustomAttributes(Type attributeType, bool inherit) {
                    return _type.MergeAttributes(attributeType, _info, inherit, ref _cache); 
                } 

                // 
                // Merges our custom attributes in with those of the member info.
                //
                public override object[] GetCustomAttributes(bool inherit) {
                    return _type.MergeAttributes(null, _info, inherit, ref _cache); 
                }
 
                // 
                // Determines if an attribute exists in the member info
                // or in our own code. 
                //
                public override bool IsDefined(Type attributeType, bool inherit) {
                    bool isDefined = _info.IsDefined(attributeType, inherit);
                    if (!isDefined) isDefined = _type.IsDefinedInTable(attributeType, _info, inherit); 
                    return isDefined;
                } 
            } 

            // 
            // A MethodInfo that provides our custom attributes.
            //
            private class MetadataMethodInfo : MethodInfo {
 
                private MethodInfo _info;
                private MetadataType _type; 
                private AttributeMergeCache _cache; 

                internal MetadataMethodInfo(MethodInfo info, MetadataType type) { 
                    _info = info;
                    _type = type;
                }
 
                //
                // MethodInfo overrides 
                // 
                public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { return _info.ReturnTypeCustomAttributes; } }
                public override MethodAttributes Attributes { get { return _info.Attributes; } } 
                public override MethodImplAttributes GetMethodImplementationFlags() { return _info.GetMethodImplementationFlags(); }
                public override ParameterInfo[] GetParameters() { return _info.GetParameters(); }
                public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { return _info.Invoke(obj, invokeAttr, binder, parameters, culture); }
                public override RuntimeMethodHandle MethodHandle { get { return _info.MethodHandle; } } 
                public override Type DeclaringType { get { return _info.DeclaringType; } }
                public override string Name { get { return _info.Name; } } 
                public override Type ReflectedType { get { return _info.ReflectedType; } } 
                public override bool Equals(object obj) { return object.ReferenceEquals(this, obj); }
                public override int GetHashCode() { return _info.GetHashCode(); } 
                public override CallingConventions CallingConvention { get { return _info.CallingConvention; } }
                public override bool ContainsGenericParameters { get { return _info.ContainsGenericParameters; } }
                public override MethodInfo GetBaseDefinition() { return _info.GetBaseDefinition(); }
                public override Type[] GetGenericArguments() { return _info.GetGenericArguments(); } 
                public override MethodInfo GetGenericMethodDefinition() { return _info.GetGenericMethodDefinition(); }
                public override MethodBody GetMethodBody() { return _info.GetMethodBody(); } 
                public override bool IsGenericMethod { get { return _info.IsGenericMethod; } } 
                public override bool IsGenericMethodDefinition { get { return _info.IsGenericMethodDefinition; } }
                public override MethodInfo MakeGenericMethod(params Type[] typeArguments) { return _info.MakeGenericMethod(typeArguments); } 
                public override MemberTypes MemberType { get { return _info.MemberType; } }
                public override int MetadataToken { get { return _info.MetadataToken; } }
                public override Module Module { get { return _info.Module; } }
                public override ParameterInfo ReturnParameter { get { return _info.ReturnParameter; } } 
                public override Type ReturnType { get { return _info.ReturnType; } }
                public override string ToString() { return _info.ToString(); ; } 
 
                //
                // Merges our custom attributes in with those of the member info. 
                //
                public override object[] GetCustomAttributes(Type attributeType, bool inherit) {
                    return _type.MergeAttributes(attributeType, _info, inherit, ref _cache);
                } 

                // 
                // Merges our custom attributes in with those of the member info. 
                //
                public override object[] GetCustomAttributes(bool inherit) { 
                    return _type.MergeAttributes(null, _info, inherit, ref _cache);
                }

                // 
                // Determines if an attribute exists in the member info
                // or in our own code. 
                // 
                public override bool IsDefined(Type attributeType, bool inherit) {
                    bool isDefined = _info.IsDefined(attributeType, inherit); 
                    if (!isDefined) isDefined = _type.IsDefinedInTable(attributeType, _info, inherit);
                    return isDefined;
                }
            } 
        }
    } 
} 

// 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