Implement MachineKey.Protect and MachineKey.Unprotect
[mono.git] / mcs / class / System / System.ComponentModel / PropertyDescriptor.cs
1 //
2 // System.ComponentModel.PropertyDescriptor.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 // (C) 2008 Novell, Inc.  http://www.novell.com
12 //
13
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System;
36 using System.Collections;
37 using System.Reflection;
38 using System.Runtime.InteropServices;
39
40 namespace System.ComponentModel
41 {
42         [ComVisible (true)]
43         public abstract class PropertyDescriptor : MemberDescriptor
44         {
45                 TypeConverter converter;
46
47                 protected PropertyDescriptor (MemberDescriptor reference)
48                 : base (reference)
49                 {
50                 }
51
52                 protected PropertyDescriptor (MemberDescriptor reference, Attribute [] attrs)
53                 : base (reference, attrs)
54                 {
55                 }
56
57                 protected PropertyDescriptor (string name, Attribute [] attrs)
58                 : base (name, attrs)
59                 {
60                 }
61
62                 public abstract Type ComponentType { get; }
63
64                 public virtual TypeConverter Converter {
65                         get {
66                                 if (converter == null && PropertyType != null) {
67                                         TypeConverterAttribute at = (TypeConverterAttribute) Attributes [typeof(TypeConverterAttribute)];
68                                         if (at != null && at != TypeConverterAttribute.Default) {
69                                                 Type converterType = GetTypeFromName (at.ConverterTypeName);
70                                                 if (converterType != null && typeof (TypeConverter).IsAssignableFrom (converterType))
71                                                         converter = (TypeConverter)CreateInstance (converterType);
72                                         }
73                                         if (converter == null)
74                                                 converter = TypeDescriptor.GetConverter (PropertyType);
75                                 }
76                                 return converter;
77                         }
78                 }
79
80                 public virtual bool IsLocalizable {
81                         get {
82                                 foreach (Attribute attr in AttributeArray){
83                                         if (attr is LocalizableAttribute)
84                                                 return ((LocalizableAttribute) attr).IsLocalizable;
85                                 }
86
87                                 return false;
88                         }
89                 }
90
91                 public abstract bool IsReadOnly { get; }
92
93                 public abstract Type PropertyType { get; }
94
95                 public virtual bool SupportsChangeEvents {
96                         get { return false; }
97                 }
98
99                 public DesignerSerializationVisibility SerializationVisibility {
100                         get {
101                                 foreach (Attribute attr in AttributeArray) {
102                                         if (attr is DesignerSerializationVisibilityAttribute){
103                                                 DesignerSerializationVisibilityAttribute a;
104
105                                                 a = (DesignerSerializationVisibilityAttribute) attr;
106
107                                                 return a.Visibility;
108                                         }
109                                 }
110
111                                 return DesignerSerializationVisibility.Visible;
112                         }
113                 }
114
115                 Hashtable notifiers;
116
117                 public virtual void AddValueChanged (object component, EventHandler handler)
118                 {
119                         EventHandler component_notifiers;
120
121                         if (component == null)
122                                 throw new ArgumentNullException ("component");
123
124                         if (handler == null)
125                                 throw new ArgumentNullException ("handler");
126
127                         if (notifiers == null)
128                                 notifiers = new Hashtable ();
129
130                         component_notifiers = (EventHandler) notifiers [component];
131
132                         if (component_notifiers != null) {
133                                 component_notifiers += handler;
134                                 notifiers [component] = component_notifiers;
135                         } else {
136                                 notifiers [component] = handler;
137                         }
138                 }
139
140                 public virtual void RemoveValueChanged (object component, System.EventHandler handler)
141                 {
142                         EventHandler component_notifiers;
143
144                         if (component == null)
145                                 throw new ArgumentNullException ("component");
146
147                         if (handler == null)
148                                 throw new ArgumentNullException ("handler");
149
150                         if (notifiers == null) return;
151
152                         component_notifiers = (EventHandler) notifiers [component];
153                         component_notifiers -= handler;
154                         
155                         if (component_notifiers == null)
156                                 notifiers.Remove (component);
157                         else
158                                 notifiers [component] = component_notifiers;
159                 }
160
161                 protected override void FillAttributes (IList attributeList)
162                 {
163                         base.FillAttributes (attributeList);
164                 }
165
166                 protected override object GetInvocationTarget (Type type, object instance)
167                 {
168                         if (type == null)
169                                 throw new ArgumentNullException ("type");
170                         if (instance == null)
171                                 throw new ArgumentNullException ("instance");
172
173                         if (instance is CustomTypeDescriptor) {
174                                 CustomTypeDescriptor ctd = (CustomTypeDescriptor) instance;
175                                 return ctd.GetPropertyOwner (this);
176                         }
177
178                         return base.GetInvocationTarget (type, instance);
179                 }
180
181                 protected internal EventHandler GetValueChangedHandler (object component)
182                 {
183                         if (component == null || notifiers == null)
184                                 return null;
185
186                         return (EventHandler) notifiers [component];
187                 }
188
189                 protected virtual void OnValueChanged (object component, EventArgs e)
190                 {
191                         if (notifiers == null)
192                                 return;
193
194                         EventHandler component_notifiers = (EventHandler) notifiers [component];
195
196                         if (component_notifiers == null)
197                                 return;
198
199                         component_notifiers (component, e);
200                 }
201
202                 public abstract object GetValue (object component);
203
204                 public abstract void SetValue (object component, object value);
205
206                 public abstract void ResetValue (object component);
207
208                 public abstract bool CanResetValue (object component);
209
210                 public abstract bool ShouldSerializeValue (object component);
211
212                 protected object CreateInstance (Type type)
213                 {
214                         if (type == null || PropertyType == null)
215                                 return null;
216
217                         object instance = null;
218                         Type[] paramTypes = new Type[] { typeof (Type) };
219                         ConstructorInfo ctor = type.GetConstructor (paramTypes);
220                         if (ctor != null) {
221                                 object[] parameters = new object[] { PropertyType };
222                                 instance = TypeDescriptor.CreateInstance (null, type, paramTypes, parameters);
223                         } else {
224                                 instance = TypeDescriptor.CreateInstance (null, type, null, null);
225                         }
226                         return instance;
227                 }
228
229                 public override bool Equals(object obj)
230                 {
231                         if (!base.Equals (obj)) return false;
232                         PropertyDescriptor other = obj as PropertyDescriptor;
233                         if (other == null) return false;
234                         return other.PropertyType == PropertyType;
235                 }
236
237                 public PropertyDescriptorCollection GetChildProperties()
238                 {
239                         return GetChildProperties (null, null);
240                 }
241
242                 public PropertyDescriptorCollection GetChildProperties(object instance)
243                 {
244                         return GetChildProperties (instance, null);
245                 }
246
247                 public PropertyDescriptorCollection GetChildProperties(Attribute[] filter)
248                 {
249                         return GetChildProperties (null, filter);
250                 }
251
252                 public override int GetHashCode() 
253                 {
254                         return base.GetHashCode ();
255                 }
256
257                 public virtual PropertyDescriptorCollection GetChildProperties (object instance, Attribute[] filter)
258                 {
259                         return TypeDescriptor.GetProperties (instance, filter);
260                 }
261
262                 public virtual object GetEditor (Type editorBaseType)
263                 {
264                         Type t = null;
265                         Attribute [] atts = AttributeArray;
266                         
267                         if (atts != null && atts.Length != 0) {
268                                 foreach (Attribute a in atts) {
269                                         EditorAttribute ea = a as EditorAttribute;
270                                         
271                                         if (ea == null)
272                                                 continue;
273                                         
274                                         t = GetTypeFromName (ea.EditorTypeName);
275                                         if (t != null && t.IsSubclassOf(editorBaseType))
276                                                 break;
277                                 }
278                         }
279
280                         object editor = null;
281                         if (t != null)
282                                 editor = CreateInstance (t);
283                         if (editor == null)
284                                 editor = TypeDescriptor.GetEditor (PropertyType, editorBaseType);
285                         return editor;
286                 }
287
288                 protected Type GetTypeFromName (string typeName)
289                 {
290                         if (typeName == null || ComponentType == null || typeName.Trim ().Length == 0)
291                                 return null;
292
293                         Type type = Type.GetType (typeName);
294                         if (type == null) {
295                                 // Try to strip the type typeName only
296                                 int index = typeName.IndexOf (",");
297                                 if (index != -1)
298                                         typeName = typeName.Substring (0, index);
299                                 type = ComponentType.Assembly.GetType (typeName);
300                         } 
301                         return type;
302                 }
303         }
304 }