Consider the following code.
Object obj;
PropertyDescriptorCollection A = TypeDescriptor.GetProperties(obj);
PropertyInfo[] B = obj.GetType().GetProperti
The TypeDescriptor
class returns PropertyDescriptor
objects that represent the properties in the type of obj
as well as any other properties that were contributed to the object itself or to its type.
The component model is actually quite complex, but as you describe, the basic implementation of TypeDescriptor.GetProperties()
will return ReflectPropertyDescriptor instances that represent an indirection to typical PropertyInfo
objects. You can use PropertyDescriptor
objects very much like PropertyInfo
objects: they can be used to get and set the value of the property and they have attributes.
For DependencyObject
instances in WPF, TypeDescriptor.GetProperties()
also returns attached properties. These PropertyDescriptor
objects in this case provide an indirection to the dependency object model rather than to reflection.
In the component designer, it is possible to use ICustomTypeDescriptor
or TypeDescriptionProviderAttribute
(and maybe some other techniques) to create your own PropertyDescriptor
objects at runtime or at designtime. In any case, it is possible that the properties returned from Type.GetProperties()
may very well differ from those returned from TypeDescriptor
, depending on the context.
The TypeDescriptor
class is used in designers, so that they can interact with the design-time environment. In particular, designers can override and extend various features of TypeDescriptor
, but not Type
.
One good example is working with data-bound controls. The DataSource
property is of type System.Object
, yet at design-time, that property is replaced with a new property that has a richer design-time UI.
obj.GetType().GetProperties()
does not return a PropertyDescriptorCollection
, it returns a System.Reflection.PropertyInfo[]
. The PropertyInfo
class does, as you suggest, represent only actual properties created on the object. A PropertyDescriptor
is either a custom concrete child of the PropertyDescriptor
class (implemented by the type defining the custom descriptor), or is an instance of the sealed internal class ReflectPropertyDescriptor
that uses the PropertyInfo
class to provide dynamic invocation of the property.
So for a class that does not define a custom descriptor, you will functionally get the same objects back, though the PropertyDescriptor
is abstracting away the PropertyInfo
.