2008-05-29 Ivan N. Zlatev <contact@i-nz.net>
authorIvan Zlatev <ivan@ivanz.com>
Thu, 29 May 2008 16:40:27 +0000 (16:40 -0000)
committerIvan Zlatev <ivan@ivanz.com>
Thu, 29 May 2008 16:40:27 +0000 (16:40 -0000)
* TypeDescriptor.cs: GetAttributes must retrieve the attributes of
the type, the base types and the interfaces the type implements.
[Fix part of bug #394310]
* TypeDescriptorTests.cs: Add test that verifies that GetAttributes
retrieves the attributes of the type, the base types and the
interfaces the type implements.

svn path=/trunk/mcs/; revision=104438

mcs/class/System/System.ComponentModel/ChangeLog
mcs/class/System/System.ComponentModel/TypeDescriptor.cs
mcs/class/System/Test/System.ComponentModel/ChangeLog
mcs/class/System/Test/System.ComponentModel/TypeDescriptorTests.cs

index 9319fc664456a623d8cab95f97b97834c47d58c2..a6022b9bdaf8b24256010c90e53605816820fac1 100644 (file)
@@ -1,3 +1,9 @@
+2008-05-29  Ivan N. Zlatev  <contact@i-nz.net>
+
+       * TypeDescriptor.cs: GetAttributes must retrieve the attributes of 
+       the type, the base types and the interfaces the type implements.
+       [Fix part of bug #394310]
+
 2008-05-21  Atsushi Enomoto  <atsushi@ximian.com>
 
        * INotifyPropertyChanging.cs, PropertyChangingEventArgs.cs,
index b2e45ffb2773d9da8e24b5c8b45783c078f22174..c5c04229333c2a26305f8d9f16025e368d4169e5 100644 (file)
@@ -972,22 +972,43 @@ public sealed class TypeDescriptor
                                return _attributes;
                        
                        bool cache = true;
-                       object[] ats = _infoType.GetCustomAttributes (true);
-                       Hashtable t = new Hashtable ();
+                       ArrayList attributesList = new ArrayList ();
+
+                       // 1) Attributes of the type
+                       foreach (Attribute attribute in _infoType.GetCustomAttributes (false))
+                               attributesList.Add (attribute);
+
+                       // 2) Attributes of the type's implemented interfaces and their interfaces as well
+                       foreach (Type inface in _infoType.GetInterfaces ())
+                               foreach (Attribute attribute in TypeDescriptor.GetAttributes (inface))
+                                       attributesList.Add (attribute);
+
+                       // 3) Attributes of the base types
+                       Type baseType = _infoType.BaseType;
+                       while (baseType != null && baseType != typeof (object)) {
+                               foreach (Attribute attribute in baseType.GetCustomAttributes (false))
+                                       attributesList.Add (attribute);
+                               baseType = baseType.BaseType;
+                       }
+
+                       // Filter out duplicate attributes, so that the type and its interfaces
+                       // have higher precedence than the base types.
+                       Hashtable attributesTable = new Hashtable ();
+                       for (int i = attributesList.Count - 1; i >= 0; i--) {
+                               Attribute attribute = (Attribute)attributesList[i];
+                               attributesTable[attribute.TypeId] = attribute;
+                       }
 
-                       for (int i = ats.Length -1; i >= 0; i--)
-                               t [((Attribute) ats[i]).TypeId] = ats[i];
-                                       
                        if (comp != null && comp.Site != null) 
                        {
                                ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) comp.Site.GetService (typeof(ITypeDescriptorFilterService));
                                if (filter != null)
-                                       cache = filter.FilterAttributes (comp, t);
+                                       cache = filter.FilterAttributes (comp, attributesTable);
                        }
-                       
-                       ArrayList atts = new ArrayList ();
-                       atts.AddRange (t.Values);
-                       AttributeCollection attCol = new AttributeCollection (atts);
+
+                       Attribute[] attributes = new Attribute[attributesTable.Values.Count];
+                       attributesTable.Values.CopyTo (attributes, 0);
+                       AttributeCollection attCol = new AttributeCollection (attributes);
                        if (cache)
                                _attributes = attCol;
                        return attCol;
index 35a889873e4e19e52193de3ce5aa8f7fb264152b..bb74b988189f7e4e1b5b272a3fb05791b65ee5c7 100644 (file)
@@ -1,3 +1,9 @@
+2008-05-29  Ivan N. Zlatev  <contact@i-nz.net>
+
+       * TypeDescriptorTests.cs: Add test that verifies that GetAttributes 
+       retrieves the attributes of the type, the base types and the 
+       interfaces the type implements.
+
 2008-05-05  Ivan N. Zlatev  <contact@i-nz.net>
 
        * TypeDescriptorTests.cs: Add test for handling write-only properties.
index 0494fa37cfdb3908c1e493a1ae516a187a83c35f..29f1ccccac667ba2efed617d88c5f1db64013a73 100644 (file)
@@ -227,6 +227,7 @@ namespace MonoTests.System.ComponentModel
                        set { prop = value; }
                }
 
+               [Browsable (false)]
                public string YetAnotherProperty
                {
                        get { return null; }
@@ -328,11 +329,13 @@ namespace MonoTests.System.ComponentModel
                }
        }
 
+       [Browsable (false)]
        public interface ITestInterface
        {
                void TestFunction ();
        }
-       
+
+       [Serializable]
        public class TestClass
        {
                public TestClass()
@@ -341,6 +344,13 @@ namespace MonoTests.System.ComponentModel
                void TestFunction ()
                {}
        }
+
+       [DescriptionAttribute ("bla")]
+       public class TestDerivedClass : TestClass, ITestInterface
+       {
+               public void TestFunction ()
+               {}
+       }
        
        public struct TestStruct
        {
@@ -546,6 +556,10 @@ namespace MonoTests.System.ComponentModel
                                }
                        }
                        Assert.IsTrue (found, "#E4");
+
+                       // Shows that attributes are retrieved from the current type, the base types 
+                       // and the implemented by the type interfaces.
+                       Assert.AreEqual (3, TypeDescriptor.GetAttributes (typeof (TestDerivedClass)).Count, "#F1");
                }
                
                [Test]
@@ -783,13 +797,20 @@ namespace MonoTests.System.ComponentModel
                                        yetAnotherPropsFound++;
                        }
 
-                       Assert.AreEqual (1, anotherPropsFound, "#G2");
-
                        // GetProperties does not return the base type property in the case 
                        // where both the "new" keyword is used and also the Property type is different 
                        // (Type.GetProperties does return both properties)
                        //
-                       Assert.AreEqual (1, yetAnotherPropsFound, "#G3");
+                       Assert.AreEqual (1, anotherPropsFound, "#G2");
+                       Assert.IsNotNull (derivedCol["AnotherProperty"].Attributes[typeof (DescriptionAttribute)], "#G3");
+                       Assert.AreEqual (1, yetAnotherPropsFound, "#G4");
+
+                       // Verify that we return the derived "new" property when 
+                       // filters are applied that match the parent property
+                       // 
+                       PropertyDescriptorCollection filteredCol = TypeDescriptor.GetProperties (typeof(MyDerivedComponent), 
+                                                                                                new Attribute[] { BrowsableAttribute.Yes });
+                       Assert.IsNotNull (filteredCol["YetAnotherProperty"], "#G5");
 
                        // GetProperties does not return write-only properties (ones without a getter)
                        //