In Test/System.ComponentModel:
[mono.git] / mcs / class / System / System.ComponentModel / TypeDescriptor.cs
index 5be97a9e0b988065620174c6134701f7655a9a38..91b78bd8e15b8dbc5a45401309c9d184bb698552 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
 using System.Collections;
 using System.Reflection;
 using System.Globalization;
 using System.ComponentModel.Design;
+using System.Security.Permissions;
 
 namespace System.ComponentModel
 {
 
 public sealed class TypeDescriptor
 {
-       private static readonly string creatingDefaultConverters = "creatingDefaultConverters";
+       private static readonly object creatingDefaultConverters = new object ();
        private static Hashtable defaultConverters;
        private static IComNativeDescriptorHandler descriptorHandler;
        private static Hashtable componentTable = new Hashtable ();
@@ -72,6 +72,7 @@ public sealed class TypeDescriptor
                return null;
        }
 
+       [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
        public static EventDescriptor CreateEvent (Type componentType,
                                                   string name,
                                                   Type type,
@@ -80,6 +81,7 @@ public sealed class TypeDescriptor
                return new ReflectionEventDescriptor (componentType, name, type, attributes);
        }
 
+       [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
        public static EventDescriptor CreateEvent (Type componentType,
                                                   EventDescriptor oldEventDescriptor,
                                                   Attribute [] attributes)
@@ -87,6 +89,7 @@ public sealed class TypeDescriptor
                return new ReflectionEventDescriptor (componentType, oldEventDescriptor, attributes);
        }
 
+       [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
        public static PropertyDescriptor CreateProperty (Type componentType,
                                                         string name,
                                                         Type type,
@@ -95,6 +98,7 @@ public sealed class TypeDescriptor
                return new ReflectionPropertyDescriptor (componentType, name, type, attributes);
        }
 
+       [ReflectionPermission (SecurityAction.LinkDemand, TypeInformation = true, MemberAccess = true)]
        public static PropertyDescriptor CreateProperty (Type componentType,
                                                         PropertyDescriptor oldPropertyDescriptor,
                                                         Attribute [] attributes)
@@ -124,7 +128,7 @@ public sealed class TypeDescriptor
                    return ((ICustomTypeDescriptor) component).GetAttributes ();
                } else {
                        IComponent com = component as IComponent;
-                       if (com != null)
+                       if (com != null && com.Site != null)
                                return GetComponentInfo (com).GetAttributes ();
                        else
                                return GetTypeInfo (component.GetType()).GetAttributes ();
@@ -142,7 +146,12 @@ public sealed class TypeDescriptor
                    throw new ArgumentNullException ("component", "component cannot be null");
 
                if (noCustomTypeDesc == false && component is ICustomTypeDescriptor) {
-                   return ((ICustomTypeDescriptor) component).GetClassName ();
+                   String res = ((ICustomTypeDescriptor) component).GetClassName ();
+                       if (res == null)
+                               res = ((ICustomTypeDescriptor) component).GetComponentName ();
+                       if (res == null)
+                               res = component.GetType ().FullName;
+                       return res;
                } else {
                    return component.GetType ().FullName;
                }
@@ -164,13 +173,17 @@ public sealed class TypeDescriptor
                        IComponent c = component as IComponent;
                        if (c != null && c.Site != null)
                                return c.Site.Name;
+#if NET_2_0
+                       return null;
+#else
                        return component.GetType().Name;
+#endif
                }
        }
 
        public static TypeConverter GetConverter (object component)
        {
-               return GetConverter (component.GetType ());
+               return GetConverter (component, false);
        }
 
        public static TypeConverter GetConverter (object component, bool noCustomTypeDesc)
@@ -204,9 +217,6 @@ public sealed class TypeDescriptor
        private static Hashtable DefaultConverters
        {
                get {
-                       if (defaultConverters != null)
-                               return defaultConverters;
-
                        lock (creatingDefaultConverters) {
                                if (defaultConverters != null)
                                        return defaultConverters;
@@ -260,10 +270,10 @@ public sealed class TypeDescriptor
                                return new ArrayConverter ();
                        }
                }
-               \r
-               if (t == null)\r
-                       t = FindConverterType (type);\r
-\r
+               
+               if (t == null)
+                       t = FindConverterType (type);
+
                if (t != null) {
                        Exception exc = null;
                        try {
@@ -280,29 +290,29 @@ public sealed class TypeDescriptor
                }
 
                return new ReferenceConverter (type);    // Default?
-       }\r
-\r
-       private static Type FindConverterType (Type type)\r
-       {\r
-               Type t = null;\r
-               \r
-               // Is there a default converter\r
-               t = (Type) DefaultConverters [type];\r
-               if (t != null)\r
-                       return t;\r
-               \r
-               // Find default converter with a type this type is assignable to\r
-               foreach (Type defType in DefaultConverters.Keys) {\r
-                       if (defType.IsInterface && defType.IsAssignableFrom (type)) {\r
-                               return (Type) DefaultConverters [defType];\r
-                       }\r
-               }\r
-               \r
-               // Nothing found, try the same with our base type\r
-               if (type.BaseType != null)\r
-                       return FindConverterType (type.BaseType);\r
-               else\r
-                       return null;\r
+       }
+
+       private static Type FindConverterType (Type type)
+       {
+               Type t = null;
+               
+               // Is there a default converter
+               t = (Type) DefaultConverters [type];
+               if (t != null)
+                       return t;
+               
+               // Find default converter with a type this type is assignable to
+               foreach (Type defType in DefaultConverters.Keys) {
+                       if (defType.IsInterface && defType.IsAssignableFrom (type)) {
+                               return (Type) DefaultConverters [defType];
+                       }
+               }
+               
+               // Nothing found, try the same with our base type
+               if (type.BaseType != null)
+                       return FindConverterType (type.BaseType);
+               else
+                       return null;
        }
 
        public static EventDescriptor GetDefaultEvent (Type componentType)
@@ -321,7 +331,7 @@ public sealed class TypeDescriptor
                        return ((ICustomTypeDescriptor) component).GetDefaultEvent ();
                else {
                        IComponent com = component as IComponent;
-                       if (com != null)
+                       if (com != null && com.Site != null)
                                return GetComponentInfo (com).GetDefaultEvent ();
                        else
                                return GetTypeInfo (component.GetType()).GetDefaultEvent ();
@@ -344,7 +354,7 @@ public sealed class TypeDescriptor
                        return ((ICustomTypeDescriptor) component).GetDefaultProperty ();
                else {
                        IComponent com = component as IComponent;
-                       if (com != null)
+                       if (com != null && com.Site != null)
                                return GetComponentInfo (com).GetDefaultProperty ();
                        else
                                return GetTypeInfo (component.GetType()).GetDefaultProperty ();
@@ -389,10 +399,29 @@ public sealed class TypeDescriptor
                return GetEditor (component, editorBaseType, false);
        }
 
-       [MonoTODO]
        public static object GetEditor (object component, Type editorBaseType, bool noCustomTypeDesc)
        {
-               throw new NotImplementedException ();
+               if (component == null)
+                       throw new ArgumentNullException ("component");
+               if (editorBaseType == null)
+                       throw new ArgumentNullException ("editorBaseType");
+               
+               if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
+                       return ((ICustomTypeDescriptor) component).GetEditor (editorBaseType);
+
+               object [] atts = component.GetType ().GetCustomAttributes (typeof (EditorAttribute), true);
+               if (atts.Length == 0)
+                       return null;
+               string target = editorBaseType.AssemblyQualifiedName;
+               
+               foreach (EditorAttribute ea in atts){
+                       if (ea.EditorBaseTypeName == target){
+                               Type t = Type.GetType (ea.EditorTypeName, true);
+
+                               return Activator.CreateInstance (t);
+                       }
+               }
+               return null;
        }
 
        public static EventDescriptorCollection GetEvents (object component)
@@ -412,7 +441,15 @@ public sealed class TypeDescriptor
 
        public static EventDescriptorCollection GetEvents (object component, bool noCustomTypeDesc)
        {
-               return GetEvents (component, null, noCustomTypeDesc);
+               if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
+                       return ((ICustomTypeDescriptor) component).GetEvents ();
+               else {
+                       IComponent com = component as IComponent;
+                       if (com != null && com.Site != null)
+                               return GetComponentInfo (com).GetEvents ();
+                       else
+                               return GetTypeInfo (component.GetType()).GetEvents ();
+               }
        }
 
        public static EventDescriptorCollection GetEvents (Type componentType, Attribute [] attributes)
@@ -426,7 +463,7 @@ public sealed class TypeDescriptor
                        return ((ICustomTypeDescriptor) component).GetEvents (attributes);
                else {
                        IComponent com = component as IComponent;
-                       if (com != null)
+                       if (com != null && com.Site != null)
                                return GetComponentInfo (com).GetEvents (attributes);
                        else
                                return GetTypeInfo (component.GetType()).GetEvents (attributes);
@@ -450,11 +487,14 @@ public sealed class TypeDescriptor
 
        public static PropertyDescriptorCollection GetProperties (object component, Attribute [] attributes, bool noCustomTypeDesc)
        {
+               if (component == null)
+                       return PropertyDescriptorCollection.Empty;
+
                if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
                        return ((ICustomTypeDescriptor) component).GetProperties (attributes);
                else {
                        IComponent com = component as IComponent;
-                       if (com != null)
+                       if (com != null && com.Site != null)
                                return GetComponentInfo (com).GetProperties (attributes);
                        else
                                return GetTypeInfo (component.GetType()).GetProperties (attributes);
@@ -463,7 +503,18 @@ public sealed class TypeDescriptor
 
        public static PropertyDescriptorCollection GetProperties (object component, bool noCustomTypeDesc)
        {
-               return GetProperties (component, null, noCustomTypeDesc);
+               if (component == null)
+                       return PropertyDescriptorCollection.Empty;
+
+               if (!noCustomTypeDesc && (component is ICustomTypeDescriptor))
+                       return ((ICustomTypeDescriptor) component).GetProperties ();
+               else {
+                       IComponent com = component as IComponent;
+                       if (com != null && com.Site != null)
+                               return GetComponentInfo (com).GetProperties ();
+                       else
+                               return GetTypeInfo (component.GetType()).GetProperties ();
+               }
        }
 
        public static PropertyDescriptorCollection GetProperties (Type componentType, Attribute [] attributes)
@@ -486,7 +537,9 @@ public sealed class TypeDescriptor
        }
 
        public static IComNativeDescriptorHandler ComNativeDescriptorHandler {
+               [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
                get { return descriptorHandler; }
+               [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
                set { descriptorHandler = value; }
        }
 
@@ -565,7 +618,8 @@ public sealed class TypeDescriptor
        {
                if (component != null && component.Site != null) {
                        ITypeResolutionService resver = (ITypeResolutionService) component.Site.GetService (typeof(ITypeResolutionService));
-                       if (resver != null) return resver.GetType (typeName, true, false);
+                       if (resver != null)
+                               return resver.GetType (typeName, true, false);
                }
                
                Type t = Type.GetType (typeName);
@@ -600,39 +654,45 @@ public sealed class TypeDescriptor
                public EventDescriptorCollection GetEvents (Attribute[] attributes)
                {
                        EventDescriptorCollection evs = GetEvents ();
-                       if (attributes == null) return evs;
-                       else return evs.Filter (attributes);
+                       if (attributes == null)
+                               return evs;
+                       else
+                               return evs.Filter (attributes);
                }
                
                public PropertyDescriptorCollection GetProperties (Attribute[] attributes)
                {
                        PropertyDescriptorCollection props = GetProperties ();
-                       if (attributes == null) return props;
-                       else return props.Filter (attributes);
+                       if (attributes == null)
+                               return props;
+                       else
+                               return props.Filter (attributes);
                }
                
                public EventDescriptor GetDefaultEvent ()
                {
-                       if (_gotDefaultEvent) return _defaultEvent;
+                       if (_gotDefaultEvent)
+                               return _defaultEvent;
                        
                        DefaultEventAttribute attr = (DefaultEventAttribute) GetAttributes()[typeof(DefaultEventAttribute)];
                        if (attr == null || attr.Name == null) 
                                _defaultEvent = null;
                        else {
-                               // WTF? 
+                               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 accepts this and returns
+                               // 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.
-                               EventDescriptorCollection events = GetEvents ();
-                               _defaultEvent = events [attr.Name];
                                if (_defaultEvent == null && events.Count > 0)
                                        _defaultEvent = events [0];
+#endif
                        }
                        _gotDefaultEvent = true;
                        return _defaultEvent;
@@ -640,16 +700,15 @@ public sealed class TypeDescriptor
                
                public PropertyDescriptor GetDefaultProperty ()
                {
-                       if (_gotDefaultProperty) return _defaultProperty;
+                       if (_gotDefaultProperty)
+                               return _defaultProperty;
                        
                        DefaultPropertyAttribute attr = (DefaultPropertyAttribute) GetAttributes()[typeof(DefaultPropertyAttribute)];
                        if (attr == null || attr.Name == null) 
                                _defaultProperty = null;
                        else {
-                               PropertyInfo ei = _infoType.GetProperty (attr.Name);
-                               if (ei == null)
-                                       throw new ArgumentException ("Property '" + attr.Name + "' not found in class " + _infoType);
-                               _defaultProperty = new ReflectionPropertyDescriptor (ei);
+                               PropertyDescriptorCollection properties = GetProperties ();
+                               _defaultProperty = properties[attr.Name];
                        }
                        _gotDefaultProperty = true;
                        return _defaultProperty;
@@ -657,13 +716,19 @@ public sealed class TypeDescriptor
                
                protected AttributeCollection GetAttributes (IComponent comp)
                {
-                       if (_attributes != null) return _attributes;
+                       if (_attributes != null)
+                               return _attributes;
                        
                        bool cache = true;
                        object[] ats = _infoType.GetCustomAttributes (true);
                        Hashtable t = new Hashtable ();
-                       foreach (Attribute at in ats)
-                               t [at.TypeId] = at;
+
+                       // Filter the custom attributes, so that only the top
+                       // level of the same type are left.
+                       //
+                       for (int i = ats.Length -1; i >= 0; i--) {
+                               t [((Attribute) ats[i]).TypeId] = ats[i];
+                       }
                                        
                        if (comp != null && comp.Site != null) 
                        {
@@ -674,7 +739,8 @@ public sealed class TypeDescriptor
                        ArrayList atts = new ArrayList ();
                        atts.AddRange (t.Values);
                        AttributeCollection attCol = new AttributeCollection (atts);
-                       if (cache) _attributes = attCol;
+                       if (cache)
+                               _attributes = attCol;
                        return attCol;
                }
        }
@@ -697,7 +763,8 @@ public sealed class TypeDescriptor
                
                public override EventDescriptorCollection GetEvents ()
                {
-                       if (_events != null) return _events;
+                       if (_events != null)
+                               return _events;
                        
                        bool cache = true;
                        EventInfo[] events = _component.GetType().GetEvents ();
@@ -707,7 +774,6 @@ public sealed class TypeDescriptor
                                        
                        if (_component.Site != null) 
                        {
-                               Console.WriteLine ("filtering events...");
                                ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
                                cache = filter.FilterEvents (_component, t);
                        }
@@ -721,10 +787,11 @@ public sealed class TypeDescriptor
                
                public override PropertyDescriptorCollection GetProperties ()
                {
-                       if (_properties != null) return _properties;
+                       if (_properties != null)
+                               return _properties;
                        
                        bool cache = true;
-                       PropertyInfo[] props = _component.GetType().GetProperties ();
+                       PropertyInfo[] props = _component.GetType().GetProperties (BindingFlags.Instance | BindingFlags.Public);
                        Hashtable t = new Hashtable ();
                        foreach (PropertyInfo pr in props)
                                t [pr.Name] = new ReflectionPropertyDescriptor (pr);
@@ -734,11 +801,12 @@ public sealed class TypeDescriptor
                                ITypeDescriptorFilterService filter = (ITypeDescriptorFilterService) _component.Site.GetService (typeof(ITypeDescriptorFilterService));
                                cache = filter.FilterProperties (_component, t);
                        }
-                       
-                       ArrayList atts = new ArrayList ();
-                       atts.AddRange (t.Values);
-                       PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (atts);
-                       if (cache) _properties = attCol;
+
+                       PropertyDescriptor[] descriptors = new PropertyDescriptor[t.Values.Count];
+                       t.Values.CopyTo (descriptors, 0);
+                       PropertyDescriptorCollection attCol = new PropertyDescriptorCollection (descriptors, true);
+                       if (cache)
+                               _properties = attCol;
                        return attCol;
                }
        }
@@ -759,7 +827,8 @@ public sealed class TypeDescriptor
                
                public override EventDescriptorCollection GetEvents ()
                {
-                       if (_events != null) return _events;
+                       if (_events != null)
+                               return _events;
                        
                        EventInfo[] events = InfoType.GetEvents ();
                        EventDescriptor[] descs = new EventDescriptor [events.Length];
@@ -772,14 +841,16 @@ public sealed class TypeDescriptor
                
                public override PropertyDescriptorCollection GetProperties ()
                {
-                       if (_properties != null) return _properties;
+                       if (_properties != null)
+                               return _properties;
                        
-                       PropertyInfo[] props = InfoType.GetProperties ();
-                       PropertyDescriptor[] descs = new PropertyDescriptor [props.Length];
+                       PropertyInfo[] props = InfoType.GetProperties (BindingFlags.Instance | BindingFlags.Public);
+                       ArrayList descs = new ArrayList (props.Length);
                        for (int n=0; n<props.Length; n++)
-                               descs [n] = new ReflectionPropertyDescriptor (props[n]);
+                               if (props [n].GetIndexParameters ().Length == 0)
+                                       descs.Add (new ReflectionPropertyDescriptor (props[n]));
 
-                       _properties = new PropertyDescriptorCollection (descs);
+                       _properties = new PropertyDescriptorCollection ((PropertyDescriptor[]) descs.ToArray (typeof (PropertyDescriptor)), true);
                        return _properties;
                }
        }