1 //------------------------------------------------------------------------------
2 // <copyright file="TypeDescriptionProvider.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 namespace System.ComponentModel {
10 using System.Collections;
11 using System.Reflection;
12 using System.Security.Permissions;
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
19 [HostProtection(SharedState = true)]
20 public abstract class TypeDescriptionProvider
22 private TypeDescriptionProvider _parent;
23 private EmptyCustomTypeDescriptor _emptyDescriptor;
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.
33 protected TypeDescriptionProvider()
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.
45 protected TypeDescriptionProvider(TypeDescriptionProvider parent)
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.
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.
59 public virtual object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
63 return _parent.CreateInstance(provider, objectType, argTypes, args);
66 if (objectType == null) {
67 throw new ArgumentNullException("objectType");
70 return SecurityUtils.SecureCreateInstance(objectType, args);
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.
84 public virtual IDictionary GetCache(object instance)
88 return _parent.GetCache(instance);
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.
108 public virtual ICustomTypeDescriptor GetExtendedTypeDescriptor(object instance)
112 return _parent.GetExtendedTypeDescriptor(instance);
115 if (_emptyDescriptor == null) {
116 _emptyDescriptor = new EmptyCustomTypeDescriptor();
119 return _emptyDescriptor;
122 protected internal virtual IExtenderProvider[] GetExtenderProviders(object instance)
126 return _parent.GetExtenderProviders(instance);
129 if (instance == null)
131 throw new ArgumentNullException("instance");
133 return new IExtenderProvider[0];
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.
142 /// If not overridden, the default implementation of this method will call
143 /// GetTypeDescriptor.GetComponentName.
145 public virtual string GetFullComponentName(object component) {
146 if (_parent != null) {
147 return _parent.GetFullComponentName(component);
150 return GetTypeDescriptor(component).GetComponentName();
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.
158 public Type GetReflectionType(Type objectType)
160 return GetReflectionType(objectType, null);
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.
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.
172 public Type GetReflectionType(object instance)
174 if (instance == null)
176 throw new ArgumentNullException("instance");
179 return GetReflectionType(instance.GetType(), instance);
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.
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.
191 public virtual Type GetReflectionType(Type objectType, object instance)
195 return _parent.GetReflectionType(objectType, instance);
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.
207 public virtual Type GetRuntimeType(Type reflectionType)
211 return _parent.GetRuntimeType(reflectionType);
214 if (reflectionType == null)
216 throw new ArgumentNullException("reflectionType");
219 if (reflectionType.GetType().Assembly == typeof(object).Assembly)
221 return reflectionType;
224 return reflectionType.UnderlyingSystemType;
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
235 public ICustomTypeDescriptor GetTypeDescriptor(Type objectType)
237 return GetTypeDescriptor(objectType, null);
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
248 public ICustomTypeDescriptor GetTypeDescriptor(object instance)
250 if (instance == null)
252 throw new ArgumentNullException("instance");
255 return GetTypeDescriptor(instance.GetType(), instance);
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
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
272 public virtual ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
276 return _parent.GetTypeDescriptor(objectType, instance);
279 if (_emptyDescriptor == null) {
280 _emptyDescriptor = new EmptyCustomTypeDescriptor();
283 return _emptyDescriptor;
287 /// This method returns true if the type is "supported" by the type descriptor
288 /// and its chain of type description providers.
290 public virtual bool IsSupportedType(Type type)
294 throw new ArgumentNullException("type");
299 return _parent.IsSupportedType(type);
306 /// A simple empty descriptor that is used as a placeholder for times
307 /// when the user does not provide their own.
309 private sealed class EmptyCustomTypeDescriptor : CustomTypeDescriptor {