Inheritance: IList, ICollection, IEnumerable
		public void Find ()
		{
			EventDescriptor descA = new MockEventDescriptor ("hehe_\u0061\u030a", null);
			EventDescriptor descB = new MockEventDescriptor ("heh_\u00e5", null);
			EventDescriptor descC = new MockEventDescriptor ("Foo", null);
			EventDescriptor descD = new MockEventDescriptor ("FOo", null);
			EventDescriptor descE = new MockEventDescriptor ("Aim", null);
			EventDescriptor descF = new MockEventDescriptor ("Bar", null);

			EventDescriptorCollection col = new EventDescriptorCollection (
				new EventDescriptor [] { descA, descB, descC, descD, descE, descF });

#if NET_2_0
			Assert.IsNull (col.Find ("heh_\u0061\u030a", false), "#1");
			Assert.IsNull (col.Find ("hehe_\u00e5", false), "#2");
#else
			Assert.AreSame (descB, col.Find ("heh_\u0061\u030a", false), "#1");
			Assert.AreSame (descA, col.Find ("hehe_\u00e5", false), "#2");
#endif
			Assert.AreSame (descA, col.Find ("hehe_\u0061\u030a", false), "#3");
			Assert.AreSame (descB, col.Find ("heh_\u00e5", false), "#4");
			Assert.IsNull (col.Find ("foo", false), "#5");
			Assert.AreSame (descC, col.Find ("foo", true), "#6");
			Assert.AreSame (descD, col.Find ("FOo", false), "#7");
			Assert.AreSame (descC, col.Find ("FOo", true), "#8");
			Assert.IsNull (col.Find ("fOo", false), "#9");
			Assert.AreSame (descC, col.Find ("fOo", true), "#10");
			Assert.IsNull (col.Find ("AIm", false), "#11");
			Assert.AreSame (descE, col.Find ("AIm", true), "#12");
			Assert.IsNull (col.Find ("AiM", false), "#13");
			Assert.AreSame (descE, col.Find ("AiM", true), "#14");
			Assert.AreSame (descE, col.Find ("Aim", false), "#15");
			Assert.AreSame (descE, col.Find ("Aim", true), "#16");
		}
Exemplo n.º 2
0
        public ClassInstance(Type wrappedType, Type objectInstanceType)
        {
            _wrappedType = wrappedType;

            // Create a wrapper for each non-collection property.
            _classProperties = _wrappedType
                .GetProperties()
                .Select(p => ClassMemberIndependent.Intercept(new ClassMemberProperty(p, objectInstanceType)))
                .Concat<ClassMember>(_wrappedType
                    .GetFields()
                    .Select(f => ClassMemberIndependent.Intercept(new ClassMemberField(f, objectInstanceType))))
                .ToList();
            _classProperties.AddRange(
                (from method in _wrappedType.GetMethods()
                 where method.ReturnType == typeof(void) && method.GetParameters().Length == 0
                 let can = (from p in _classProperties
                            where p.Name == "Can" + method.Name && p.PropertyType == typeof(bool)
                            select p).FirstOrDefault()
                 select new ClassMemberCommand(method, can, objectInstanceType)).ToList());
            _propertyDescriptors = new PropertyDescriptorCollection(_classProperties.ToArray());

            // Create a pass-through for each event.
            _classEvents = _wrappedType
                .GetEvents()
                .Select(e => new ClassEvent(e))
                .ToList();
            _eventDescriptors = new EventDescriptorCollection(_classEvents.ToArray());
        }
Exemplo n.º 3
0
 public ProxyTypeDescriptor(Type type)
 {
     Meta = TypeMeta.Get(type);
     ProxyType = typeof(PlatformProxy<>).MakeGenericType(type);
     _properties = Meta.Members.Select(m => new ProxyPropertyDescriptor(this, m)).ToArray();
     _propertyCollection = new PropertyDescriptorCollection(_properties);
     _events = new EventDescriptorCollection(type.GetEvents().Select(e => new ProxyEventDescriptor(e)).ToArray());
 }
		public void Find_Key_Null ()
		{
			EventDescriptorCollection descriptors = new EventDescriptorCollection (
				new EventDescriptor[] { new MockEventDescriptor ("A", "X"),
					new MockEventDescriptor ("b", "Y")});

			Assert.IsNull (descriptors.Find (null, false), "#1");
			Assert.IsNull (descriptors.Find (null, true), "#2");
		}
Exemplo n.º 5
0
        public System.ComponentModel.PropertyDescriptorCollection GetEventProperties(System.ComponentModel.EventDescriptorCollection events)
        {
            ArrayList props = new ArrayList();

            foreach (EventDescriptor e in events)
            {
                props.Add(GetEventProperty(e));
            }

            return(new PropertyDescriptorCollection((PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor))));
        }
 PropertyDescriptorCollection IEventBindingService.GetEventProperties(EventDescriptorCollection events)
 {
     if (events == null)
     {
         throw new ArgumentNullException("events");
     }
     List<PropertyDescriptor> list = new List<PropertyDescriptor>(events.Count);
     for (int i = 0; i < events.Count; i++)
     {
         if (!this.HasGenericArgument(events[i]))
         {
             PropertyDescriptor item = new EventPropertyDescriptor(events[i], this);
             list.Add(item);
         }
     }
     return new PropertyDescriptorCollection(list.ToArray());
 }
 PropertyDescriptorCollection IEventBindingService.GetEventProperties(EventDescriptorCollection events)
 {
     if (events == null)
     {
         throw new ArgumentNullException("events");
     }
     PropertyDescriptor[] props = new PropertyDescriptor[events.Count];
     if (this._eventProperties == null)
     {
         this._eventProperties = new Hashtable();
     }
     for (int i = 0; i < events.Count; i++)
     {
         object eventHashCode = this.GetEventDescriptorHashCode(events[i]);
         props[i] = (PropertyDescriptor) this._eventProperties[eventHashCode];
         if (props[i] == null)
         {
             props[i] = new EventPropertyDescriptor(events[i], this);
             this._eventProperties[eventHashCode] = props[i];
         }
     }
     return new PropertyDescriptorCollection(props);
 }
Exemplo n.º 8
0
        public override EventDescriptorCollection GetEvents()
        {
            if (_events != null)
            {
                return(_events);
            }

            bool cache = true;

            EventInfo[] events = _component.GetType().GetEvents();
            Hashtable   t      = new Hashtable();

            foreach (EventInfo ev in events)
            {
                t [ev.Name] = new ReflectionEventDescriptor(ev);
            }

            if (_component.Site != null)
            {
                ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService)_component.Site.GetService(typeof(ITypeDescriptorFilterService));
                if (filter != null)
                {
                    cache = filter.FilterEvents(_component, t);
                }
            }

            ArrayList atts = new ArrayList();

            atts.AddRange(t.Values);
            EventDescriptorCollection attCol = new EventDescriptorCollection(atts);

            if (cache)
            {
                _events = attCol;
            }
            return(attCol);
        }
Exemplo n.º 9
0
        public EventDescriptor GetDefaultEvent()
        {
            if (_gotDefaultEvent)
            {
                return(_defaultEvent);
            }

            DefaultEventAttribute attr = (DefaultEventAttribute)GetAttributes()[typeof(DefaultEventAttribute)];

            if (attr == null || attr.Name == null)
            {
                _defaultEvent = null;
            }
            else
            {
                EventDescriptorCollection events = GetEvents();
                _defaultEvent = events [attr.Name];
#if !NET_2_0
                // In our test case (TypeDescriptorTest.TestGetDefaultEvent), we have
                // a scenario where a custom filter adds the DefaultEventAttribute,
                // but its FilterEvents method removes the event the
                // DefaultEventAttribute applied to.  .NET 1.x accepts this and returns
                // the *other* event defined in the class.
                //
                // Consequently, we know we have a DefaultEvent, but we need to check
                // and ensure that the requested event is unfiltered.  If it is, just
                // grab the first element in the collection.
                if (_defaultEvent == null && events.Count > 0)
                {
                    _defaultEvent = events [0];
                }
#endif
            }
            _gotDefaultEvent = true;
            return(_defaultEvent);
        }
Exemplo n.º 10
0
        /// <devdoc>
        ///     Metadata merging is the second stage of our metadata pipeline.  This stage
        ///     merges extended metdata with primary metadata, and stores it in 
        ///     the cache if it is available.
        /// </devdoc>
        private static ICollection PipelineMerge(int pipelineType, ICollection primary, ICollection secondary, object instance, IDictionary cache)
        {
            // If there is no secondary collection, there is nothing to merge.
            //
            if (secondary == null || secondary.Count == 0)
            {
                return primary;
            }

            // Next, if we were given a cache, see if it has accurate data.
            //
            if (cache != null)
            {
                ICollection mergeCache = cache[_pipelineMergeKeys[pipelineType]] as ICollection;
                if (mergeCache != null && mergeCache.Count == (primary.Count + secondary.Count))
                {
                    // Walk the merge cache.
                    IEnumerator mergeEnum = mergeCache.GetEnumerator();
                    IEnumerator primaryEnum = primary.GetEnumerator();
                    bool match = true;

                    while(primaryEnum.MoveNext() && mergeEnum.MoveNext())
                    {
                        if (primaryEnum.Current != mergeEnum.Current)
                        {
                            match = false;
                            break;
                        }
                    }

                    if (match)
                    {
                        IEnumerator secondaryEnum = secondary.GetEnumerator();

                        while(secondaryEnum.MoveNext() && mergeEnum.MoveNext())
                        {
                            if (secondaryEnum.Current != mergeEnum.Current)
                            {
                                match = false;
                                break;
                            }
                        }
                    }

                    if (match)
                    {
                        return mergeCache;
                    }
                }
            }

            // Our cache didn't match.  We need to merge metadata and return
            // the merged copy.  We create an array list here, rather than
            // an array, because we want successive sections of the 
            // pipeline to be able to modify it.
            //
            ArrayList list = new ArrayList(primary.Count + secondary.Count);
            foreach(object obj in primary)
            {
                list.Add(obj);
            }
            foreach(object obj in secondary)
            {
                list.Add(obj);
            }

            if (cache != null)
            {
                ICollection cacheValue;

                switch(pipelineType)
                {
                    case PIPELINE_ATTRIBUTES:
                        Attribute[] attrArray = new Attribute[list.Count];
                        list.CopyTo(attrArray, 0);
                        cacheValue = new AttributeCollection(attrArray);
                        break;

                    case PIPELINE_PROPERTIES:
                        PropertyDescriptor[] propArray = new PropertyDescriptor[list.Count];
                        list.CopyTo(propArray, 0);
                        cacheValue = new PropertyDescriptorCollection(propArray, true);
                        break;

                    case PIPELINE_EVENTS:
                        EventDescriptor[] eventArray = new EventDescriptor[list.Count];
                        list.CopyTo(eventArray, 0);
                        cacheValue = new EventDescriptorCollection(eventArray, true);
                        break;

                    default:
                        Debug.Fail("unknown pipeline type");
                        cacheValue = null;
                        break;
                }

                Trace("Pipeline : Merge results being cached for {0}", instance.GetType().Name);
                cache[_pipelineMergeKeys[pipelineType]] = cacheValue;
                cache.Remove(_pipelineFilterKeys[pipelineType]);
                cache.Remove(_pipelineAttributeFilterKeys[pipelineType]);
            }

            return list;
        }
 /// <devdoc>
 ///     Refreshes the contents of this type descriptor.  This does not
 ///     actually requery, but it will clear our state so the next
 ///     query re-populates.
 /// </devdoc>
 internal void Refresh()
 {
     _attributes = null;
     _events = null;
     _properties = null;
     _converter = null;
     _editors = null;
     _editorTypes = null;
     _editorCount = 0;
 }
		public override EventDescriptorCollection GetEvents ()
		{
			if (_events != null)
				return _events;
			
			EventInfo[] events = InfoType.GetEvents ();
			EventDescriptor[] descs = new EventDescriptor [events.Length];
			for (int n=0; n<events.Length; n++)
				descs [n] = new ReflectionEventDescriptor (events[n]);

			_events = new EventDescriptorCollection (descs);
			return _events;
		}
Exemplo n.º 13
0
        private EventDescriptorCollection FilterEvents(EventDescriptorCollection origEvents)
        {
            // Create an enumerator containing only the events that are not in the provided list of event names
            // and fill an array with those selected events
            IEnumerable<EventDescriptor> selectedEvents = origEvents.OfType<EventDescriptor>().Where(e => _excludeBrowsableEvents.Contains(e.Name));
            //IEnumerable<EventDescriptor> selectedEvents = origEvents.OfType<EventDescriptor>().Where(e => !_excludeBrowsableEvents.Contains(e.Name));
            EventDescriptor[] descriptors = selectedEvents.ToArray();

            // Return an EventDescriptorCollection containing only the filtered descriptors
            EventDescriptorCollection newCollection = new EventDescriptorCollection(descriptors);

            return newCollection;
        }
Exemplo n.º 14
0
 private EventDescriptorCollection(EventDescriptorCollection copyFrom,
                                   String[] names, IComparer comparer)
 {
     list = (ArrayList)(copyFrom.list.Clone());
     InternalSort(names, comparer);
 }
Exemplo n.º 15
0
		PropertyDescriptorCollection IEventBindingService.GetEventProperties (EventDescriptorCollection events)
		{
			if (events == null)
				throw new ArgumentNullException ("events");

			List<PropertyDescriptor> properties = new List <PropertyDescriptor>();
			foreach (EventDescriptor eventDescriptor in events)
				properties.Add (((IEventBindingService)this).GetEventProperty (eventDescriptor));
				
			return new PropertyDescriptorCollection (properties.ToArray ());
		}
 public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes, bool noCustomTypeDesc)
 {
     ICollection events;
     if (component == null)
     {
         return new EventDescriptorCollection(null, true);
     }
     ICustomTypeDescriptor descriptor = GetDescriptor(component, noCustomTypeDesc);
     if (component is ICustomTypeDescriptor)
     {
         events = descriptor.GetEvents(attributes);
         if (noCustomTypeDesc)
         {
             ICustomTypeDescriptor extendedDescriptor = GetExtendedDescriptor(component);
             if (extendedDescriptor != null)
             {
                 ICollection secondary = extendedDescriptor.GetEvents(attributes);
                 events = PipelineMerge(2, events, secondary, component, null);
             }
         }
         else
         {
             events = PipelineFilter(2, events, component, null);
             events = PipelineAttributeFilter(2, events, attributes, component, null);
         }
     }
     else
     {
         IDictionary cache = GetCache(component);
         events = descriptor.GetEvents(attributes);
         events = PipelineInitialize(2, events, cache);
         ICustomTypeDescriptor descriptor3 = GetExtendedDescriptor(component);
         if (descriptor3 != null)
         {
             ICollection is4 = descriptor3.GetEvents(attributes);
             events = PipelineMerge(2, events, is4, component, cache);
         }
         events = PipelineFilter(2, events, component, cache);
         events = PipelineAttributeFilter(2, events, attributes, component, cache);
     }
     EventDescriptorCollection descriptors = events as EventDescriptorCollection;
     if (descriptors == null)
     {
         EventDescriptor[] array = new EventDescriptor[events.Count];
         events.CopyTo(array, 0);
         descriptors = new EventDescriptorCollection(array, true);
     }
     return descriptors;
 }
 public static EventDescriptorCollection GetEvents(Type componentType, Attribute[] attributes)
 {
     if (componentType == null)
     {
         return new EventDescriptorCollection(null, true);
     }
     EventDescriptorCollection events = GetDescriptor(componentType, "componentType").GetEvents(attributes);
     if ((attributes != null) && (attributes.Length > 0))
     {
         ArrayList list = FilterMembers(events, attributes);
         if (list != null)
         {
             events = new EventDescriptorCollection((EventDescriptor[]) list.ToArray(typeof(EventDescriptor)), true);
         }
     }
     return events;
 }
Exemplo n.º 18
0
		[Test] // Sort (String [], IComparer)
		public void Sort4 ()
		{
			EventDescriptorCollection descriptors;
			EventDescriptorCollection sorted;

			EventDescriptor descA = new MockEventDescriptor ("Foo", "B");
			EventDescriptor descB = new MockEventDescriptor ("Aim", "C");
			EventDescriptor descC = new MockEventDescriptor ("Bim", "A");
			EventDescriptor descD = new MockEventDescriptor ("AIm", "E");
			EventDescriptor descE = new MockEventDescriptor ("Boo", "D");
			EventDescriptor descF = new MockEventDescriptor ("FOo", "F");

			EventDescriptor [] props = new EventDescriptor [] {
				descA, descB, descC, descD, descE, descF };
			descriptors = new EventDescriptorCollection (props);

			Assert.AreSame (descA, descriptors [0], "#A1");
			Assert.AreSame (descB, descriptors [1], "#A2");
			Assert.AreSame (descC, descriptors [2], "#A3");
			Assert.AreSame (descD, descriptors [3], "#A4");
			Assert.AreSame (descE, descriptors [4], "#A5");
			Assert.AreSame (descF, descriptors [5], "#A6");

			sorted = descriptors.Sort (new string [] { "B", "Foo", null, "A", "Boo" },
				new CategoryComparer ());

			Assert.AreSame (descA, descriptors [0], "#B1");
			Assert.AreSame (descB, descriptors [1], "#B2");
			Assert.AreSame (descC, descriptors [2], "#B3");
			Assert.AreSame (descD, descriptors [3], "#B4");
			Assert.AreSame (descE, descriptors [4], "#B5");
			Assert.AreSame (descF, descriptors [5], "#B6");

			Assert.AreSame (descA, sorted [0], "#C1");
			Assert.AreSame (descE, sorted [1], "#C2");
			Assert.AreSame (descC, sorted [2], "#C3");
			Assert.AreSame (descB, sorted [3], "#C4");
			Assert.AreSame (descD, sorted [4], "#C5");
			Assert.AreSame (descF, sorted [5], "#C6");

			sorted = descriptors.Sort ((string []) null, new CategoryComparer ());

			Assert.AreSame (descA, descriptors [0], "#D1");
			Assert.AreSame (descB, descriptors [1], "#D2");
			Assert.AreSame (descC, descriptors [2], "#D3");
			Assert.AreSame (descD, descriptors [3], "#D4");
			Assert.AreSame (descE, descriptors [4], "#D5");
			Assert.AreSame (descF, descriptors [5], "#D6");

			Assert.AreSame (descC, sorted [0], "#E1");
			Assert.AreSame (descA, sorted [1], "#E2");
			Assert.AreSame (descB, sorted [2], "#E3");
			Assert.AreSame (descE, sorted [3], "#E4");
			Assert.AreSame (descD, sorted [4], "#E5");
			Assert.AreSame (descF, sorted [5], "#E6");

			sorted = descriptors.Sort (new string [] { "B", "Foo", null, "A", "Boo" },
				(Comparer) null);

			Assert.AreSame (descA, descriptors [0], "#F1");
			Assert.AreSame (descB, descriptors [1], "#F2");
			Assert.AreSame (descC, descriptors [2], "#F3");
			Assert.AreSame (descD, descriptors [3], "#F4");
			Assert.AreSame (descE, descriptors [4], "#F5");
			Assert.AreSame (descF, descriptors [5], "#F6");

			Assert.AreSame (descA, sorted [0], "#G1");
			Assert.AreSame (descE, sorted [1], "#G2");
			Assert.AreSame (descB, sorted [2], "#G3");
			Assert.AreSame (descD, sorted [3], "#G4");
			Assert.AreSame (descC, sorted [4], "#G5");
			Assert.AreSame (descF, sorted [5], "#G6");

			sorted = descriptors.Sort ((string []) null, (Comparer) null);

			Assert.AreSame (descA, descriptors [0], "#H1");
			Assert.AreSame (descB, descriptors [1], "#H2");
			Assert.AreSame (descC, descriptors [2], "#H3");
			Assert.AreSame (descD, descriptors [3], "#H4");
			Assert.AreSame (descE, descriptors [4], "#H5");
			Assert.AreSame (descF, descriptors [5], "#H6");

			Assert.AreSame (descB, sorted [0], "#I1");
			Assert.AreSame (descD, sorted [1], "#I2");
			Assert.AreSame (descC, sorted [2], "#I3");
			Assert.AreSame (descE, sorted [3], "#I4");
			Assert.AreSame (descA, sorted [4], "#I5");
			Assert.AreSame (descF, sorted [5], "#I6");
		}
Exemplo n.º 19
0
		private void AssertReadOnly (EventDescriptorCollection descriptors, string testCase)
		{
			MockEventDescriptor desc = new MockEventDescriptor (
				"Date", "NOW");

			try {
				descriptors.Add (desc);
				Assert.Fail (testCase + "#1");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			// ensure read-only check if performed before value is checked
			try {
				descriptors.Add (null);
				Assert.Fail (testCase + "#2");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				descriptors.Clear ();
				Assert.Fail (testCase + "#3");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				descriptors.Insert (0, desc);
				Assert.Fail (testCase + "#4");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			// ensure read-only check if performed before value is checked
			try {
				descriptors.Insert (0, null);
				Assert.Fail (testCase + "#5");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				descriptors.Remove (desc);
				Assert.Fail (testCase + "#6");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			// ensure read-only check if performed before value is checked
			try {
				descriptors.Remove (null);
				Assert.Fail (testCase + "#7");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				descriptors.RemoveAt (0);
				Assert.Fail (testCase + "#8");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			IList list = (IList) descriptors;
			Assert.IsTrue (((IList) descriptors).IsReadOnly, testCase + "#9");
#if NET_2_0
			Assert.IsTrue (((IList) descriptors).IsFixedSize, testCase + "#10");
#else
			Assert.IsFalse (((IList) descriptors).IsFixedSize, testCase + "#10");
#endif

			try {
				list.Add (desc);
				Assert.Fail (testCase + "#11");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			// ensure read-only check if performed before value is checked
			try {
				list.Add (null);
				Assert.Fail (testCase + "#12");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				list.Clear ();
				Assert.Fail (testCase + "#13");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				list.Insert (0, desc);
				Assert.Fail (testCase + "#14");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			// ensure read-only check if performed before value is checked
			try {
				list.Insert (0, null);
				Assert.Fail (testCase + "#15");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				list.Remove (desc);
				Assert.Fail (testCase + "#16");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			// ensure read-only check if performed before value is checked
			try {
				list.Remove (null);
				Assert.Fail (testCase + "#17");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				list.RemoveAt (0);
				Assert.Fail (testCase + "#18");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			try {
				list[0] = desc;
				Assert.Fail (testCase + "#19");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}

			// ensure read-only check if performed before value is checked
			try {
				list[0] = null;
				Assert.Fail (testCase + "#20");
			} catch (NotSupportedException) {
				// read-only collection cannot be modified
			}
		}
Exemplo n.º 20
0
            /// <devdoc> 
            ///     Retrieves events that satisfy all of the passed-in attributes. 
            ///     For an event to satisfy a particular attribute, the attribute must be 
            ///     present in the event's attribute list, or the attribute must match it's 
            ///     own default.  The returned array is sorted based on the sort parameter. 
            /// </devdoc> 
            public EventDescriptorCollection GetEvents(object component, Attribute[] attributes, bool noFilter) {
                // Worst case event collision scenario is two sets of events.  Much cheaper than
                // a constant lock.
                //
                if (this.events == null) {
                    this.events = new EventDescriptorCollection(new MemberList(this).GetEvents(), true);
                }

                EventDescriptorCollection filteredEvents = events;

                if (component is IComponent) {
                    ITypeDescriptorFilterService tf = (ITypeDescriptorFilterService)GetService(component, typeof(ITypeDescriptorFilterService));
                    
                    if (!noFilter && tf != null) {
                        // The component's site is interested in filtering events.  See if we
                        // have filtered them before.  If so, then we're done.  Otherwise we
                        // need to filter.
                        //
                        IDictionaryService ds = (IDictionaryService)GetService(component, typeof(IDictionaryService));
                        if (ds != null) {
                            EventDescriptorCollection savedEvents = null;
                             
                            lock(ds) {
                                savedEvents = (EventDescriptorCollection)ds.GetValue(typeof(EventDescriptorCollection));
                            }
                            
                            if (savedEvents != null) {
                            
                                // Check that the filter that was used to create these attributes is the same
                                // filter we currently have.  People may replace the filter, and if we do 
                                // we must refresh the cache.
                                //
                                object savedFilter = ds.GetValue(typeof(ITypeDescriptorFilterService));
                                if (savedFilter == null || savedFilter == tf) {
                                    filteredEvents = savedEvents;
                                }
                            }
                        }
                        
                        if (filteredEvents == events) {
                            Hashtable filterTable = new Hashtable(events.Count);
                            
                            if (events != null) {
                                foreach (EventDescriptor ev in events) {
                                    filterTable[ev.Name] = ev;
                                }
                            }
                            
                            bool cache = tf.FilterEvents((IComponent)component, filterTable);
                            EventDescriptor[] temp = new EventDescriptor[filterTable.Values.Count];
                            filterTable.Values.CopyTo(temp, 0);
                            filteredEvents = new EventDescriptorCollection(temp, true);
                            
                            if (ds != null && cache) {
                                lock(ds) {
                                    ds.SetValue(typeof(EventDescriptorCollection), filteredEvents);
                                    ds.SetValue(typeof(ITypeDescriptorFilterService), tf);
                                }
                            }
                        }
                    }
                }
                
                if (attributes != null && attributes.Length > 0) {
                    ArrayList list = new ArrayList(filteredEvents);
                    FilterMembers(typeof(EventDescriptor), list, attributes);
                    EventDescriptor[] temp = new EventDescriptor[list.Count];
                    list.CopyTo(temp, 0);
                    filteredEvents = new EventDescriptorCollection(temp, true);
                }
                
                return filteredEvents;
            }
	private EventDescriptorCollection(EventDescriptorCollection copyFrom,
									  String[] names, IComparer comparer)
			{
				list = (ArrayList)(copyFrom.list.Clone());
				InternalSort(names, comparer);
			}
Exemplo n.º 22
0
            internal EventDescriptorCollection FilterEvents(object component, Attribute[] attributes, EventDescriptorCollection events) {
                EventDescriptorCollection filteredEvents = events;

                if (component is IComponent) {
                    ITypeDescriptorFilterService tf = (ITypeDescriptorFilterService)GetService(component, typeof(ITypeDescriptorFilterService));
                    if (tf != null) {
                        Hashtable filterTable = new Hashtable(events.Count);
                        
                        if (events != null) {
                            foreach (EventDescriptor ev in events) {
                                filterTable[ev.Name] = ev;
                            }
                        }
                        
                        bool cache = tf.FilterEvents((IComponent)component, filterTable);
                        EventDescriptor[] temp = new EventDescriptor[filterTable.Values.Count];
                        filterTable.Values.CopyTo(temp, 0);
                        filteredEvents = new EventDescriptorCollection(temp, true);
                    }
                }
                
                if (attributes != null && attributes.Length > 0) {
                    ArrayList list = new ArrayList(filteredEvents);
                    FilterMembers(typeof(EventDescriptor), list, attributes);
                    EventDescriptor[] temp = new EventDescriptor[list.Count];
                    list.CopyTo(temp, 0);
                    filteredEvents = new EventDescriptorCollection(temp, true);
                }
                
                return filteredEvents;
            }
		public override EventDescriptorCollection GetEvents ()
		{
			if (_events != null)
				return _events;
			
			bool cache = true;
			EventInfo[] events = _component.GetType().GetEvents ();
			Hashtable t = new Hashtable ();
			foreach (EventInfo ev in events)
				t [ev.Name] = new ReflectionEventDescriptor (ev);
					
			if (_component.Site != null) 
			{
				ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
				if (filter != null)
					cache = filter.FilterEvents (_component, t);
			}
			
			ArrayList atts = new ArrayList ();
			atts.AddRange (t.Values);
			EventDescriptorCollection attCol = new EventDescriptorCollection (atts);
			if (cache) _events = attCol;
			return attCol;
		}
Exemplo n.º 24
0
		///     Converts a set of events to a set of properties.
		PropertyDescriptorCollection IEventBindingService.GetEventProperties(EventDescriptorCollection events) 
		{

			if (events == null) 
			{
				throw new ArgumentNullException("events");
			}

			PropertyDescriptor[] props = new PropertyDescriptor[events.Count];

			// We cache the property descriptors here for speed.  Create those for
			// events that we don't have yet.
			//
			if (_eventProperties == null) 
			{
				_eventProperties = new Hashtable();
			}
            
			for (int i = 0; i < events.Count; i++) 
			{
                
				object eventHashCode = GetEventDescriptorHashCode(events[i]);

				props[i] = (PropertyDescriptor)_eventProperties[eventHashCode];

				if (props[i] == null) 
				{
					props[i] = new EventPropertyDescriptor(events[i], this);
					_eventProperties[eventHashCode] = props[i];
				}
			}

			return new PropertyDescriptorCollection(props);
		}
            /// <devdoc>
            ///     Retrieves the events for this type.
            /// </devdoc>
            internal EventDescriptorCollection GetEvents()
            {
                // Worst case collision scenario:  we don't want the perf hit
                // of taking a lock, so if we collide we will query for
                // events twice.  Not a big deal.
                //
                if (_events == null)
                {
                    TypeDescriptor.Trace("Events : Building collection for {0}", _type.Name);

                    EventDescriptor[] eventArray;
                    Dictionary<string, EventDescriptor> eventList = new Dictionary<string, EventDescriptor>(16);
                    Type baseType = _type;
                    Type objType = typeof(object);

                    do {
                        eventArray = ReflectGetEvents(baseType);
                        foreach(EventDescriptor ed in eventArray) {
                            if (!eventList.ContainsKey(ed.Name)) {
                                eventList.Add(ed.Name, ed);
                            }    
                        }
                        baseType = baseType.BaseType;
                    }
                    while(baseType != null && baseType != objType);

                    eventArray = new EventDescriptor[eventList.Count];
                    eventList.Values.CopyTo(eventArray, 0);
                    _events = new EventDescriptorCollection(eventArray, true);
                }

                return _events;
            }
Exemplo n.º 26
0
        /// <devdoc>
        ///     Gets a collection of events for a specified type of
        ///     component using a specified array of attributes as a filter.
        /// </devdoc>
        public static EventDescriptorCollection GetEvents(Type componentType, Attribute[] attributes) 
        {
            if (componentType == null) 
            {
                Debug.Fail("COMPAT:  Returning an empty collection, but you should not pass null here");
                return new EventDescriptorCollection(null, true);
            }

            EventDescriptorCollection events = GetDescriptor(componentType, "componentType").GetEvents(attributes);

            if (attributes != null && attributes.Length > 0) {
                ArrayList filteredEvents = FilterMembers(events, attributes);
                if (filteredEvents != null) {
                    events = new EventDescriptorCollection((EventDescriptor[])filteredEvents.ToArray(typeof(EventDescriptor)), true);
                }
            }
            
            DebugValidate(events, componentType, attributes);
            return events;
        }
Exemplo n.º 27
0
 PropertyDescriptorCollection IEventBindingService.GetEventProperties(EventDescriptorCollection e)
 {
     if (!(this.GetCodeDocumentLanguage() is ICodeBehindDocumentLanguage))
     {
         return new PropertyDescriptorCollection(null);
     }
     PropertyDescriptor[] properties = new PropertyDescriptor[e.Count];
     for (int i = 0; i < e.Count; i++)
     {
         properties[i] = ((IEventBindingService) this).GetEventProperty(e[i]);
     }
     return new PropertyDescriptorCollection(properties);
 }
Exemplo n.º 28
0
        /// <devdoc>
        ///     This is the last stage in our filtering pipeline.  Here, we apply any
        ///     user-defined filter.  
        /// </devdoc>
        private static ICollection PipelineAttributeFilter(int pipelineType, ICollection members, Attribute[] filter, object instance, IDictionary cache)
        {
            Debug.Assert(pipelineType != PIPELINE_ATTRIBUTES, "PipelineAttributeFilter is not supported for attributes");
            
            IList list = members as ArrayList;

            if (filter == null || filter.Length == 0)
            {
                return members;
            }

            // Now, check our cache.  The cache state is only valid
            // if the data coming into us is read-only.  If it is read-write,
            // that means something higher in the pipeline has already changed
            // it so we must recompute anyway.
            //
            if (cache != null && (list == null || list.IsReadOnly))
            {
                AttributeFilterCacheItem filterCache = cache[_pipelineAttributeFilterKeys[pipelineType]] as AttributeFilterCacheItem;
                if (filterCache != null && filterCache.IsValid(filter))
                {
                    return filterCache.FilteredMembers;
                }
            }

            // Our cache did not contain the correct state, so generate it.
            //
            if (list == null || list.IsReadOnly)
            {
                Trace("Pipeline : Filter needs to create member list for {0}", instance.GetType().Name);
                list = new ArrayList(members);
            }

            ArrayList filterResult = FilterMembers(list, filter);
            if (filterResult != null) list = filterResult;

            // And, if we have a cache, store the updated state into it for future reference.
            //
            if (cache != null)
            {
                ICollection cacheValue;

                switch(pipelineType)
                {
                    case PIPELINE_PROPERTIES:
                        PropertyDescriptor[] propArray = new PropertyDescriptor[list.Count];
                        list.CopyTo(propArray, 0);
                        cacheValue = new PropertyDescriptorCollection(propArray, true);
                        break;

                    case PIPELINE_EVENTS:
                        EventDescriptor[] eventArray = new EventDescriptor[list.Count];
                        list.CopyTo(eventArray, 0);
                        cacheValue = new EventDescriptorCollection(eventArray, true);
                        break;

                    default:
                        Debug.Fail("unknown pipeline type");
                        cacheValue = null;
                        break;
                }

                Trace("Pipeline : Attribute Filter results being cached for {0}", instance.GetType().Name);
                AttributeFilterCacheItem filterCache = new AttributeFilterCacheItem(filter, cacheValue);
                cache[_pipelineAttributeFilterKeys[pipelineType]] = filterCache;
            }

            return list;
        }
Exemplo n.º 29
0
        public static EventDescriptorCollection GetEvents(object component, Attribute[] attributes, bool noCustomTypeDesc) 
        {
            if (component == null) 
            {
                Debug.Fail("COMPAT:  Returning an empty collection, but you should not pass null here");
                return new EventDescriptorCollection(null, true);
            }

            // We create a sort of pipeline for mucking with metadata.  The pipeline
            // goes through the following process:
            //
            // 1.  Merge metadata from extenders.
            // 2.  Allow services to filter the metadata
            // 3.  If an attribute filter was specified, apply that.
            // 
            // The goal here is speed.  We get speed by not copying or
            // allocating memory.  We do this by allowing each phase of the
            // pipeline to cache its data in the object cache.  If
            // a phase makes a change to the results, this change must cause
            // successive phases to recompute their results as well.  "Results" is
            // always a collection, and the various stages of the pipeline may
            // replace or modify this collection (depending on if it's a
            // read-only IList or not).  It is possible for the orignal
            // descriptor or attribute collection to pass through the entire
            // pipeline without modification.
            // 
            ICustomTypeDescriptor typeDesc = GetDescriptor(component, noCustomTypeDesc);
            ICollection results;

            // If we are handed a custom type descriptor we have several choices of action
            // we can take.  If noCustomTypeDesc is true, it means that the custom type
            // descriptor is trying to find a baseline set of events.  In this case
            // we should merge in extended events, but we do not let designers filter
            // because we're not done with the event set yet.  If noCustomTypeDesc
            // is false, we don't do extender events because the custom type descriptor
            // has already added them.  In this case, we are doing a final pass so we
            // want to apply filtering.  Finally, if the incoming object is not a custom
            // type descriptor, we do extenders and the filter.
            //
            if (component is ICustomTypeDescriptor)
            {
                results = typeDesc.GetEvents(attributes);
                if (noCustomTypeDesc)
                {
                    ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
                    if (extDesc != null)
                    {
                        ICollection extResults = extDesc.GetEvents(attributes);
                        results = PipelineMerge(PIPELINE_EVENTS, results, extResults, component, null);
                    }
                }
                else
                {
                    results = PipelineFilter(PIPELINE_EVENTS, results, component, null);
                    results = PipelineAttributeFilter(PIPELINE_EVENTS, results, attributes, component, null);
                }
            }
            else
            {
                IDictionary cache = GetCache(component);
                results = typeDesc.GetEvents(attributes);
                results = PipelineInitialize(PIPELINE_EVENTS, results, cache);
                ICustomTypeDescriptor extDesc = GetExtendedDescriptor(component);
                if (extDesc != null)
                {
                    ICollection extResults = extDesc.GetEvents(attributes);
                    results = PipelineMerge(PIPELINE_EVENTS, results, extResults, component, cache);
                }

                results = PipelineFilter(PIPELINE_EVENTS, results, component, cache);
                results = PipelineAttributeFilter(PIPELINE_EVENTS, results, attributes, component, cache);
            }

            EventDescriptorCollection evts = results as EventDescriptorCollection;
            if (evts == null)
            {
                Trace("Events : Allocated new event collection for {0}", component.GetType().Name);
                EventDescriptor[] eventArray = new EventDescriptor[results.Count];
                results.CopyTo(eventArray, 0);
                evts = new EventDescriptorCollection(eventArray, true);
            }

            DebugValidate(evts, component, attributes, noCustomTypeDesc);

            return evts;
        }
Exemplo n.º 30
0
		[Test] // this [String]
		public void Indexer2 ()
		{
			EventDescriptor descA = new MockEventDescriptor ("hehe_\u0061\u030a", null);
			EventDescriptor descB = new MockEventDescriptor ("heh_\u00e5", null);
			EventDescriptor descC = new MockEventDescriptor ("Foo", null);
			EventDescriptor descD = new MockEventDescriptor ("FOo", null);
			EventDescriptor descE = new MockEventDescriptor ("Aim", null);
			EventDescriptor descF = new MockEventDescriptor ("Bar", null);

			EventDescriptorCollection col = new EventDescriptorCollection (
				new EventDescriptor [] { descA, descB, descC, descD, descE, descF });

#if NET_2_0
			Assert.IsNull (col ["heh_\u0061\u030a"], "#1");
			Assert.IsNull (col ["hehe_\u00e5"], "#2");
#else
			Assert.AreSame (descB, col ["heh_\u0061\u030a"], "#1");
			Assert.AreSame (descA, col ["hehe_\u00e5"], "#2");
#endif
			Assert.AreSame (descA, col ["hehe_\u0061\u030a"], "#3");
			Assert.AreSame (descB, col ["heh_\u00e5"], "#4");
			Assert.IsNull (col ["foo"], "#5");
			Assert.AreSame (descD, col ["FOo"], "#6");
			Assert.IsNull (col ["fOo"], "#7");
			Assert.IsNull (col ["AIm"], "#8");
			Assert.IsNull (col ["AiM"], "#9");
			Assert.AreSame (descE, col ["Aim"], "#10");
			Assert.IsNull (col [(string) null], "#11");
		}
Exemplo n.º 31
0
        /// <devdoc>
        ///     Metdata filtering is the third stage of our pipeline.  
        ///     In this stage we check to see if the given object is a
        ///     sited component that provides the ITypeDescriptorFilterService
        ///     object.  If it does, we allow the TDS to filter the metadata.
        ///     This will use the cache, if available, to store filtered
        ///     metdata.
        /// </devdoc>
        private static ICollection PipelineFilter(int pipelineType, ICollection members, object instance, IDictionary cache)
        {
            IComponent component = instance as IComponent;
            ITypeDescriptorFilterService componentFilter = null;

            if (component != null)
            {
                ISite site = component.Site;
                if (site != null)
                {
                    componentFilter = site.GetService(typeof(ITypeDescriptorFilterService)) as ITypeDescriptorFilterService;
                }
            }

            // If we have no filter, there is nothing for us to do.
            //
            IList list = members as ArrayList;

            if (componentFilter == null)
            {
                Debug.Assert(cache == null || list == null || !cache.Contains(_pipelineFilterKeys[pipelineType]), "Earlier pipeline stage should have removed our cache");
                return members;
            }

            // Now, check our cache.  The cache state is only valid
            // if the data coming into us is read-only.  If it is read-write,
            // that means something higher in the pipeline has already changed
            // it so we must recompute anyway.
            //
            if (cache != null && (list == null || list.IsReadOnly))
            {
                FilterCacheItem cacheItem = cache[_pipelineFilterKeys[pipelineType]] as FilterCacheItem;
                if (cacheItem != null && cacheItem.IsValid(componentFilter)) {
                    return cacheItem.FilteredMembers;
                }
            }

            // Cache either is dirty or doesn't exist.  Re-filter the members.
            // We need to build an IDictionary of key->value pairs and invoke
            // Filter* on the filter service.
            //
            OrderedDictionary filterTable = new OrderedDictionary(members.Count);
            bool cacheResults;

            switch(pipelineType)
            {
                case PIPELINE_ATTRIBUTES:
                    foreach(Attribute attr in members)
                    {
                        filterTable[attr.TypeId] = attr;
                    }
                    cacheResults = componentFilter.FilterAttributes(component, filterTable);
                    break;

                case PIPELINE_PROPERTIES:
                case PIPELINE_EVENTS:
                    foreach(MemberDescriptor desc in members)
                    {
                        string descName = desc.Name;
                        // We must handle the case of duplicate property names
                        // because extender providers can provide any arbitrary
                        // name.  Our rule for this is simple:  If we find a
                        // duplicate name, resolve it back to the extender
                        // provider that offered it and append "_" + the
                        // provider name.  If the provider has no name,
                        // then append the object hash code.
                        //
                        if (filterTable.Contains(descName)) 
                        {
                            // First, handle the new property.  Because
                            // of the order in which we added extended
                            // properties earlier in the pipeline, we can be 
                            // sure that the new property is an extender.  We
                            // cannot be sure that the existing property
                            // in the table is an extender, so we will 
                            // have to check.
                            //
                            string suffix = GetExtenderCollisionSuffix(desc);
                            Debug.Assert(suffix != null, "Name collision with non-extender property.");
                            if (suffix != null) 
                            {
                                filterTable[descName + suffix] = desc;
                            }

                            // Now, handle the original property.
                            //
                            MemberDescriptor origDesc = (MemberDescriptor)filterTable[descName];
                            suffix = GetExtenderCollisionSuffix(origDesc);
                            if (suffix != null) 
                            {
                                filterTable.Remove(descName);
                                filterTable[origDesc.Name + suffix] = origDesc;
                            }
                        }
                        else 
                        {
                            filterTable[descName] = desc;
                        }
                    }
                    if (pipelineType == PIPELINE_PROPERTIES)
                    {
                        cacheResults = componentFilter.FilterProperties(component, filterTable);
                    }
                    else
                    {
                        cacheResults = componentFilter.FilterEvents(component, filterTable);
                    }
                    break;

                default:
                    Debug.Fail("unknown pipeline type");
                    cacheResults = false;
                    break;
            }

            // See if we can re-use the IList were were passed.  If we can,
            // it is more efficient to re-use its slots than to generate new ones.
            //
            if (list == null || list.IsReadOnly)
            {
                Trace("Pipeline : Filter needs to create member list for {0}", instance.GetType().Name);
                list = new ArrayList(filterTable.Values);
            }
            else
            {
                list.Clear();
                foreach(object obj in filterTable.Values)
                {
                    list.Add(obj);
                }
            }

            // Component filter has requested that we cache these
            // new changes.  We store them as a correctly typed collection
            // so on successive invocations we can simply return.  Note that
            // we always return the IList so that successive stages in the
            // pipeline can modify it.
            //
            if (cacheResults && cache != null)
            {
                ICollection cacheValue;

                switch(pipelineType)
                {
                    case PIPELINE_ATTRIBUTES:
                        Attribute[] attrArray = new Attribute[list.Count];
                        try
                        {
                            list.CopyTo(attrArray, 0);
                        }
                        catch(InvalidCastException)
                        {
                            throw new ArgumentException(SR.GetString(SR.TypeDescriptorExpectedElementType, typeof(Attribute).FullName));
                        }
                        cacheValue = new AttributeCollection(attrArray);
                        break;

                    case PIPELINE_PROPERTIES:
                        PropertyDescriptor[] propArray = new PropertyDescriptor[list.Count];
                        try
                        {
                            list.CopyTo(propArray, 0);
                        }
                        catch(InvalidCastException)
                        {
                            throw new ArgumentException(SR.GetString(SR.TypeDescriptorExpectedElementType, typeof(PropertyDescriptor).FullName));
                        }
                        cacheValue = new PropertyDescriptorCollection(propArray, true);
                        break;

                    case PIPELINE_EVENTS:
                        EventDescriptor[] eventArray = new EventDescriptor[list.Count];
                        try
                        {
                            list.CopyTo(eventArray, 0);
                        }
                        catch(InvalidCastException)
                        {
                            throw new ArgumentException(SR.GetString(SR.TypeDescriptorExpectedElementType, typeof(EventDescriptor).FullName));
                        }
                        cacheValue = new EventDescriptorCollection(eventArray, true);
                        break;

                    default:
                        Debug.Fail("unknown pipeline type");
                        cacheValue = null;
                        break;
                }

                Trace("Pipeline : Filter results being cached for {0}", instance.GetType().Name);

                FilterCacheItem cacheItem = new FilterCacheItem(componentFilter, cacheValue);
                cache[_pipelineFilterKeys[pipelineType]] = cacheItem;
                cache.Remove(_pipelineAttributeFilterKeys[pipelineType]);
            }

            return list;
        }
Exemplo n.º 32
0
		public void ReadOnly ()
		{
			EventDescriptorCollection descriptors = new EventDescriptorCollection (
				(EventDescriptor []) null, true);
			AssertReadOnly (descriptors, "ReadOnly");
		}
Exemplo n.º 33
0
        private static void DebugValidate(EventDescriptorCollection events, Type type, Attribute[] attributes)
        {
            #if DEBUG
            if (!DebugShouldValidate(type)) return;
            EventDescriptorCollection debugEvents = DebugTypeDescriptor.GetEvents(type, attributes);
            Debug.Assert(debugEvents.Count == events.Count, "TypeDescriptor engine Validation Failure. Event counts differ.");
            foreach(EventDescriptor debugEvt in debugEvents)
            {
                EventDescriptor evt = null;
                
                foreach(EventDescriptor realEvt in events)
                {
                    if (realEvt.Name.Equals(debugEvt.Name) && realEvt.EventType == debugEvt.EventType && realEvt.ComponentType == debugEvt.ComponentType)
                    {
                        evt = realEvt;
                        break;
                    }
                }

                Debug.Assert(evt != null, "TypeDescriptor engine Validation Failure. Event " + debugEvt.Name + " does not exist or is of the wrong type.");
                if (evt != null)
                {
                    AttributeCollection attrs = evt.Attributes;
                    if (attrs[typeof(AttributeProviderAttribute)] == null)
                    {
                        AttributeCollection debugAttrs = debugEvt.Attributes;
                        DebugValidate(evt.EventType, attrs, debugAttrs);
                    }
                }
            }
            #endif
        }
Exemplo n.º 34
0
		[Test] // Sort (IComparer)
		public void Sort3 ()
		{
			EventDescriptorCollection descriptors;
			EventDescriptorCollection sorted;

			EventDescriptor descA = new MockEventDescriptor ("Foo", "B");
			EventDescriptor descB = new MockEventDescriptor ("Aim", "C");
			EventDescriptor descC = new MockEventDescriptor ("Bim", "A");
			EventDescriptor descD = new MockEventDescriptor ("AIm", "E");
			EventDescriptor descE = new MockEventDescriptor ("Boo", "D");
			EventDescriptor descF = new MockEventDescriptor ("FOo", "F");

			EventDescriptor [] props = new EventDescriptor [] {
				descA, descB, descC, descD, descE, descF };
			descriptors = new EventDescriptorCollection (props);

			Assert.AreSame (descA, descriptors [0], "#A1");
			Assert.AreSame (descB, descriptors [1], "#A2");
			Assert.AreSame (descC, descriptors [2], "#A3");
			Assert.AreSame (descD, descriptors [3], "#A4");
			Assert.AreSame (descE, descriptors [4], "#A5");
			Assert.AreSame (descF, descriptors [5], "#A6");

			sorted = descriptors.Sort (new CategoryComparer ());

			Assert.AreSame (descA, descriptors [0], "#B1");
			Assert.AreSame (descB, descriptors [1], "#B2");
			Assert.AreSame (descC, descriptors [2], "#B3");
			Assert.AreSame (descD, descriptors [3], "#B4");
			Assert.AreSame (descE, descriptors [4], "#B5");
			Assert.AreSame (descF, descriptors [5], "#B6");

			Assert.AreSame (descC, sorted [0], "#C1");
			Assert.AreSame (descA, sorted [1], "#C2");
			Assert.AreSame (descB, sorted [2], "#C3");
			Assert.AreSame (descE, sorted [3], "#C4");
			Assert.AreSame (descD, sorted [4], "#C5");
			Assert.AreSame (descF, sorted [5], "#C6");

			sorted = descriptors.Sort ((Comparer) null);

			Assert.AreSame (descA, descriptors [0], "#D1");
			Assert.AreSame (descB, descriptors [1], "#D2");
			Assert.AreSame (descC, descriptors [2], "#D3");
			Assert.AreSame (descD, descriptors [3], "#D4");
			Assert.AreSame (descE, descriptors [4], "#D5");
			Assert.AreSame (descF, descriptors [5], "#D6");

			Assert.AreSame (descB, sorted [0], "#E1");
			Assert.AreSame (descD, sorted [1], "#E2");
			Assert.AreSame (descC, sorted [2], "#E3");
			Assert.AreSame (descE, sorted [3], "#E4");
			Assert.AreSame (descA, sorted [4], "#E5");
			Assert.AreSame (descF, sorted [5], "#E6");
		}