Initial commit
[mono.git] / mcs / class / referencesource / System / compmod / system / componentmodel / TypeDescriptionProvider.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="TypeDescriptionProvider.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.ComponentModel {
8
9     using System;
10     using System.Collections;
11     using System.Reflection;
12     using System.Security.Permissions;
13
14     /// <devdoc>
15     ///     The TypeDescriptionProvider class can be thought of as a "plug-in" for 
16     ///     TypeDescriptor.  There can be multiple type description provider classes 
17     ///     all offering metadata to TypeDescriptor
18     /// </devdoc>
19     [HostProtection(SharedState = true)]
20     public abstract class TypeDescriptionProvider 
21     {
22         private TypeDescriptionProvider   _parent;
23         private EmptyCustomTypeDescriptor _emptyDescriptor;
24
25         /// <devdoc>
26         ///     There are two versions of the constructor for this class.  The empty 
27         ///     constructor is identical to using TypeDescriptionProvider(null).  
28         ///     If a child type description provider is passed into the constructor, 
29         ///     the "base" versions of all methods will call to this parent provider.  
30         ///     If no such provider is given, the base versions of the methods will 
31         ///     return empty, but valid values.
32         /// </devdoc>
33         protected TypeDescriptionProvider()
34         {
35         }
36
37         /// <devdoc>
38         ///     There are two versions of the constructor for this class.  The empty 
39         ///     constructor is identical to using TypeDescriptionProvider(null).  
40         ///     If a child type description provider is passed into the constructor, 
41         ///     the "base" versions of all methods will call to this parent provider.  
42         ///     If no such provider is given, the base versions of the methods will 
43         ///     return empty, but valid values.
44         /// </devdoc>
45         protected TypeDescriptionProvider(TypeDescriptionProvider parent)
46         {
47             _parent = parent;
48         }
49
50         /// <devdoc>
51         ///     This method is used to create an instance that can substitute for another 
52         ///     data type.   If the method is not interested in providing a substitute 
53         ///     instance, it should call base.
54         ///
55         ///     This method is prototyped as virtual, and by default returns null if no 
56         ///     parent provider was passed.  If a parent provider was passed, this 
57         ///     method will invoke the parent provider's CreateInstance method.
58         /// </devdoc>
59         public virtual object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
60         {
61             if (_parent != null)
62             {
63                 return _parent.CreateInstance(provider, objectType, argTypes, args);
64             }
65
66             if (objectType == null) {
67                 throw new ArgumentNullException("objectType");
68             }
69
70             return SecurityUtils.SecureCreateInstance(objectType, args);
71         }
72
73         /// <devdoc>
74         ///     TypeDescriptor may need to perform complex operations on collections of metadata.  
75         ///     Since types are not unloaded for the life of a domain, TypeDescriptor will 
76         ///     automatically cache the results of these operations based on type.  There are a 
77         ///     number of operations that use live object instances, however.  These operations 
78         ///     cannot be cached within TypeDescriptor because caching them would prevent the 
79         ///     object from garbage collecting.  Instead, TypeDescriptor allows for a per-object 
80         ///     cache, accessed as an IDictionary of key/value pairs, to exist on an object.  
81         ///     The GetCache method returns an instance of this cache.  GetCache will return 
82         ///     null if there is no supported cache for an object.
83         /// </devdoc>
84             public virtual IDictionary GetCache(object instance)
85         {
86             if (_parent != null)
87             {
88                 return _parent.GetCache(instance);
89             }
90
91             return null;
92         }
93
94         /// <devdoc>
95         ///     This method returns an extended custom type descriptor for the given object.  
96         ///     An extended type descriptor is a custom type descriptor that offers properties 
97         ///     that other objects have added to this object, but are not actually defined on 
98         ///     the object.  For example, in the .NET Framework Component Model, objects that 
99         ///     implement the interface IExtenderProvider can "attach" properties to other 
100         ///     objects that reside in the same logical container.  The GetTypeDescriptor 
101         ///     method does not return a type descriptor that provides these extra extended 
102         ///     properties.  GetExtendedTypeDescriptor returns the set of these extended 
103         ///     properties.  TypeDescriptor will automatically merge the results of these 
104         ///     two property collections.  Note that while the .NET Framework component 
105         ///     model only supports extended properties this API can be used for extended 
106         ///     attributes and events as well, if the type description provider supports it.
107         /// </devdoc>
108         public virtual ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
109         {
110             if (_parent != null)
111             {
112                 return _parent.GetExtendedTypeDescriptor(instance);
113             }
114
115             if (_emptyDescriptor == null) {
116                 _emptyDescriptor = new EmptyCustomTypeDescriptor();
117             }
118
119             return _emptyDescriptor;
120         }
121
122         protected internal virtual IExtenderProvider[] GetExtenderProviders(object instance)
123         {
124             if (_parent != null)
125             {
126                 return _parent.GetExtenderProviders(instance);
127             }
128
129             if (instance == null)
130             {
131                 throw new ArgumentNullException("instance");
132             }
133             return new IExtenderProvider[0];
134         }
135
136         /// <devdoc>
137         ///     The name of the specified component, or null if the component has no name.
138         ///     In many cases this will return the same value as GetComponentName. If the
139         ///     component resides in a nested container or has other nested semantics, it may
140         ///     return a different fully qualfied name.
141         ///
142         ///     If not overridden, the default implementation of this method will call
143         ///     GetTypeDescriptor.GetComponentName.
144         /// </devdoc>
145         public virtual string GetFullComponentName(object component) {
146             if (_parent != null) {
147                 return _parent.GetFullComponentName(component);
148             }
149
150             return GetTypeDescriptor(component).GetComponentName();
151         }
152
153         /// <devdoc>
154         ///     The GetReflection method is a lower level version of GetTypeDescriptor.  
155         ///     If no custom type descriptor can be located for an object, GetReflectionType 
156         ///     is called to perform normal reflection against the object.
157         /// </devdoc>
158         public Type GetReflectionType(Type objectType)
159         {
160             return GetReflectionType(objectType, null);
161         }
162
163         /// <devdoc>
164         ///     The GetReflection method is a lower level version of GetTypeDescriptor.  
165         ///     If no custom type descriptor can be located for an object, GetReflectionType 
166         ///     is called to perform normal reflection against the object.
167         ///
168         ///     This method is prototyped as virtual, and by default returns the
169         ///     object type if no parent provider was passed.  If a parent provider was passed, this 
170         ///     method will invoke the parent provider's GetReflectionType method.
171         /// </devdoc>
172         public Type GetReflectionType(object instance)
173         {
174             if (instance == null)
175             {
176                 throw new ArgumentNullException("instance");
177             }
178
179             return GetReflectionType(instance.GetType(), instance);
180         }
181
182         /// <devdoc>
183         ///     The GetReflection method is a lower level version of GetTypeDescriptor.  
184         ///     If no custom type descriptor can be located for an object, GetReflectionType 
185         ///     is called to perform normal reflection against the object.
186         ///
187         ///     This method is prototyped as virtual, and by default returns the
188         ///     object type if no parent provider was passed.  If a parent provider was passed, this 
189         ///     method will invoke the parent provider's GetReflectionType method.
190         /// </devdoc>
191         public virtual Type GetReflectionType(Type objectType, object instance)
192         {
193             if (_parent != null)
194             {
195                 return _parent.GetReflectionType(objectType, instance);
196             }
197
198             return objectType;
199         }
200
201         /// <devdoc>
202         ///     The GetRuntimeType method reverses GetReflectionType to convert a reflection type
203         ///     back into a runtime type.  Historically the Type.UnderlyingSystemType property has
204         ///     been used to return the runtime type.  This isn't exactly correct, but it needs
205         ///     to be preserved unless all type description providers are revised.
206         /// </devdoc>
207         public virtual Type GetRuntimeType(Type reflectionType)
208         {
209             if (_parent != null)
210             {
211                 return _parent.GetRuntimeType(reflectionType);
212             }
213
214             if (reflectionType == null)
215             {
216                 throw new ArgumentNullException("reflectionType");
217             }
218
219             if (reflectionType.GetType().Assembly == typeof(object).Assembly)
220             {
221                 return reflectionType;
222             }
223
224             return reflectionType.UnderlyingSystemType;
225         }
226
227         /// <devdoc>
228         ///     This method returns a custom type descriptor for the given type / object.  
229         ///     The objectType parameter is always valid, but the instance parameter may 
230         ///     be null if no instance was passed to TypeDescriptor.  The method should 
231         ///     return a custom type descriptor for the object.  If the method is not 
232         ///     interested in providing type information for the object it should 
233         ///     return base.
234         /// </devdoc>
235         public ICustomTypeDescriptor GetTypeDescriptor(Type objectType)
236         {
237             return GetTypeDescriptor(objectType, null);
238         }
239
240         /// <devdoc>
241         ///     This method returns a custom type descriptor for the given type / object.  
242         ///     The objectType parameter is always valid, but the instance parameter may 
243         ///     be null if no instance was passed to TypeDescriptor.  The method should 
244         ///     return a custom type descriptor for the object.  If the method is not 
245         ///     interested in providing type information for the object it should 
246         ///     return base.
247         /// </devdoc>
248         public ICustomTypeDescriptor GetTypeDescriptor(object instance)
249         {
250             if (instance == null)
251             {
252                 throw new ArgumentNullException("instance");
253             }
254
255             return GetTypeDescriptor(instance.GetType(), instance);
256         }
257
258         /// <devdoc>
259         ///     This method returns a custom type descriptor for the given type / object.  
260         ///     The objectType parameter is always valid, but the instance parameter may 
261         ///     be null if no instance was passed to TypeDescriptor.  The method should 
262         ///     return a custom type descriptor for the object.  If the method is not 
263         ///     interested in providing type information for the object it should 
264         ///     return base.
265         ///
266         ///     This method is prototyped as virtual, and by default returns a
267         ///     custom type descriptor that returns empty collections for all values
268         ///     if no parent provider was passed.  If a parent provider was passed, 
269         ///     this method will invoke the parent provider's GetTypeDescriptor 
270         ///     method.
271         /// </devdoc>
272         public virtual ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
273         {
274             if (_parent != null)
275             {
276                 return _parent.GetTypeDescriptor(objectType, instance);
277             }
278
279             if (_emptyDescriptor == null) {
280                 _emptyDescriptor = new EmptyCustomTypeDescriptor();
281             }
282
283             return _emptyDescriptor;
284         }
285
286         /// <devdoc>
287         ///     This method returns true if the type is "supported" by the type descriptor
288         ///     and its chain of type description providers.
289         /// </devdoc>
290         public virtual bool IsSupportedType(Type type)
291         {
292             if (type == null)
293             {
294                 throw new ArgumentNullException("type");
295             }
296
297             if (_parent != null)
298             {
299                 return _parent.IsSupportedType(type);
300             }
301
302             return true;
303         }
304
305         /// <devdoc>
306         ///     A simple empty descriptor that is used as a placeholder for times
307         ///     when the user does not provide their own.
308         /// </devdoc>
309         private sealed class EmptyCustomTypeDescriptor : CustomTypeDescriptor {
310         }
311     }
312 }
313