Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / System / System.ComponentModel / MemberDescriptor.cs
1 //
2 // System.ComponentModel.MemberDescriptor.cs
3 //
4 // Author:
5 //  Miguel de Icaza (miguel@ximian.com)
6 //  Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //  Ivan N. Zlatev <contact@i-nz.net>
8 //
9 // (C) Ximian, Inc.  http://www.ximian.com
10 // (C) 2003 Andreas Nahr
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Collections;
36 using System.Reflection;
37 using System.Runtime.InteropServices;
38 using System.ComponentModel.Design;
39 using System.Globalization;
40
41 namespace System.ComponentModel
42 {
43         [ComVisible (true)]
44         public abstract class MemberDescriptor
45         {
46                 private string name;
47                 private Attribute [] attrs; // only the attributes supplied in the ctor
48                 private AttributeCollection attrCollection;
49                 private static IComparer default_comparer;
50
51                 protected MemberDescriptor (string name, Attribute [] attrs)
52                 {
53                         this.name = name;
54                         this.attrs = attrs;
55                 }
56
57                 protected MemberDescriptor (MemberDescriptor reference, Attribute [] attrs)
58                 {
59                         name = reference.name;
60                         this.attrs = attrs;
61                 }
62
63                 protected MemberDescriptor (string name)
64                 {
65                         this.name = name;
66                 }
67
68                 protected MemberDescriptor (MemberDescriptor reference)
69                 {
70                         name = reference.name;
71                         attrs = reference.AttributeArray;
72                 }
73
74                 protected virtual Attribute [] AttributeArray {
75                         get {
76                                 ArrayList list = new ArrayList ();
77                                 if (attrs != null)
78                                         list.AddRange (attrs);
79                                 FillAttributes (list);
80                                 // For duplicate attributes, the last one added to the list is kept.
81                                 Hashtable attributes = new Hashtable ();
82                                 foreach (Attribute attribute in list)
83                                         attributes[attribute.TypeId] = attribute;
84                                 Attribute[] attributesArray = new Attribute[attributes.Values.Count];
85                                 attributes.Values.CopyTo (attributesArray, 0);
86                                 return attributesArray;
87                         }
88                         set {
89                                 attrs = value;
90                         }
91                 }
92
93                 protected virtual void FillAttributes(System.Collections.IList attributeList)
94                 {
95                         // to be overriden
96                 }
97
98                 public virtual AttributeCollection Attributes {
99                         get {
100                                 if (attrCollection == null)
101                                         attrCollection = CreateAttributeCollection ();
102                                 return attrCollection;
103                         }
104                 }
105
106                 protected virtual AttributeCollection CreateAttributeCollection ()
107                 {
108                         return new AttributeCollection (AttributeArray);
109                 }
110
111                 public virtual string Category {
112                         get {
113                                 return ((CategoryAttribute) Attributes [typeof (CategoryAttribute)]).Category;
114                         }
115                 }
116
117                 public virtual string Description {
118                         get {
119                                 foreach (Attribute attr in AttributeArray)
120                                         if (attr is DescriptionAttribute)
121                                                 return ((DescriptionAttribute) attr).Description;
122                                 return string.Empty;
123                         }
124                 }
125
126                 public virtual bool DesignTimeOnly {
127                         get {
128                                 foreach (Attribute attr in AttributeArray)
129                                         if (attr is DesignOnlyAttribute)
130                                                 return ((DesignOnlyAttribute) attr).IsDesignOnly;
131                                 return false;
132                         }
133                 }
134
135                 public virtual string DisplayName {
136                         get {
137                                 foreach (Attribute attr in AttributeArray)
138                                         if (attr is DisplayNameAttribute)
139                                                 return ((DisplayNameAttribute) attr).DisplayName;
140                                 return name;
141                         }
142                 }
143
144                 public virtual string Name {
145                         get {
146                                 return name;
147                         }
148                 }
149
150                 public virtual bool IsBrowsable {
151                         get {
152                                 foreach (Attribute attr in AttributeArray)
153                                         if (attr is BrowsableAttribute)
154                                                 return ((BrowsableAttribute) attr).Browsable;
155                                 return true;
156                         }
157                 }
158
159                 protected virtual int NameHashCode {
160                         get {
161                                 return name.GetHashCode ();
162                         }
163                 }
164
165                 public override int GetHashCode ()
166                 {
167                         return base.GetHashCode ();
168                 }
169
170                 public override bool Equals (object obj)
171                 {
172                         MemberDescriptor other = obj as MemberDescriptor;
173                         if (other == null)
174                                 return false;
175                         return other.name == name;
176                 }
177
178                 protected static ISite GetSite (object component)
179                 {
180                         if (component is Component)
181                                 return ((Component) component).Site;
182                         else
183                                 return null;
184                 }
185
186                 [Obsolete ("Use GetInvocationTarget")]
187                 protected static object GetInvokee (Type componentClass, object component)
188                 {
189                         if (component is IComponent) {
190                                 ISite site = ((IComponent) component).Site;
191                                 if (site != null && site.DesignMode) {
192                                         IDesignerHost host = site.GetService (typeof (IDesignerHost)) as IDesignerHost;
193                                         if (host != null) {
194                                                 IDesigner designer = host.GetDesigner ((IComponent) component);
195                                                 if (designer != null && componentClass.IsInstanceOfType (designer)) {
196                                                         component = designer;
197                                                 }
198                                         }
199                                 }
200                         }
201                         return component;
202                 }
203
204                 protected virtual object GetInvocationTarget (Type type, object instance)
205                 {
206                         if (type == null)
207                                 throw new ArgumentNullException ("type");
208                         if (instance == null)
209                                 throw new ArgumentNullException ("instance");
210
211                         return GetInvokee (type, instance);
212                 }
213
214                 protected static MethodInfo FindMethod(Type componentClass, string name, Type[] args, Type returnType)
215                 {
216                         return FindMethod (componentClass, name, args, returnType, true);
217                 }
218
219                 protected static MethodInfo FindMethod(Type componentClass, string name, Type[] args, Type returnType, bool publicOnly)
220                 {
221                         BindingFlags bf;
222                         if (publicOnly == true)
223                                 bf = BindingFlags.Public;
224                         else
225                                 bf = BindingFlags.NonPublic | BindingFlags.Public;
226                         // FIXME returnType is not taken into account. AFAIK methods are not allowed to only
227                         // differ by return type anyway
228                         return componentClass.GetMethod (name, bf, null, CallingConventions.Any, args, null);
229                 }
230
231                 internal static IComparer DefaultComparer {
232                         get {
233                                 if (default_comparer == null)
234                                         default_comparer = new MemberDescriptorComparer ();
235                                 return default_comparer;
236                         }
237                 }
238
239                 private class MemberDescriptorComparer : IComparer
240                 {
241                         public int Compare (object x, object y)
242                         {
243                                 return String.Compare (((MemberDescriptor)x).Name, ((MemberDescriptor)y).Name, 
244                                                        false, CultureInfo.InvariantCulture);
245                         }
246                 }
247         }
248 }