Introduction

.NET provides flexible data-binding and runtime property access, but by default
this is via reflection an is known to be relatively slow. This article uses
the power of Reflection.Emit to provide a pre-compiled (and much accelerated) implementation
for reflection properties, and demonstrates the use of TypeDescriptionProvider to
dynamically apply this implementation to types.

A lot of technical details are included, but this code is all provided in the source; as a consumer you have
to do almost nothing. Really. You may wish to jump ahead to the usage scenarios, then dip back
if you want to know what makes it all work.

Background

Data-binding (and various other runtime access) uses the System.ComponentModel; this is
how a type or instance says "I have these properties." Each property is expressed as a PropertyDescriptor,
which provides information on the underlying type, the name, and (most importantly) a GetValue() and SetValue()
method to allow access to the data. By default the framework uses
reflection to provide access to the properties defined against the types - but there
is a problem: reflection is (relatively speaking) slow (quantified below). If you use a lot
of data binding, or need to dynamically access properties at runtime, then this can be
a drain.

Specifically, the following ("SAMPLE 1", "SAMPLE 2") achieve the same thing, but perform very differently:

The latter must make a myriad of calls to verify the arguments (since everything is typed as
object), and must do a lot of work to correctly call the property getter at runtime. Our objective
is to eliminate as much of this overhead as possible.

Reflection, fortunately, is not the end of the story. In 1.1, the Framework supported the
ICustomTypeDescriptor interface; by passing an instance to GetProperties(), the system can query this
interface and supplement the properties. This is similar to how a DataRow exposes binding properties that match
the columns of the DataTable, instead of the properties on the DataRow class. But again, it is not ideal:

It requires the instance to implement the complex ICustomTypeDescriptor interface (a lot of work)

It cannot be applied to types outside of your control

It does not work when asking about a type rather than an instance

.NET 2.0 takes this further; by using a TypeDescriptionProvider, this allows us to delegate provision
of runtime type information to separate classes. More: we can actually supply providers at runtime -
meaning we can effective extend / replace the properties available. Neat.

PropertyDescriptor implementation

In order to change the performance, our end-game is to make "SAMPLE 2" run "SAMPLE 1" internally rather
than using reflection. For a single known type, this is relatively easy, if boring; we simply need to
create a PropertyDescriptor class for each property on the type, and perform the casts as compile-time:

(Here, ChainingPropertyDescriptor is a simple PropertyDescriptor implementation that supports chaining by invoking the
parent's implementation for each of the many methods.)

However, this approach is clearly only possible for types and properties we know about in advance, and even then
it would be a nightmare to keep it all up to date. That is where Reflection.Emit comes in; this is a
mechanism for meta-programming - i.e. we can (at runtime) create a set of classes just like the above.
Although other approaches (like CodeDom) are feasible, Reflection.Emit is (to my mind) the cleanest to use.
Unfortunately, it requires you to code in IL. I am not an IL expert, so my high-tech approach was to write 4
PropertyDescriptors like above, and look at the generated IL in ILDASM and Reflector:

A class entity with a class property

A class entity with a struct property

A struct entity with a class property

A struct entity with a struct property

Fortunately, the IL for these simple methods is quite simple; to illustrate with GetValue() (although a full
explanation of IL is not given here):

This is repeated for the other cited overrides (note, however, that we only override
SetValue(), AddValueChanged() and RemoveValueChanged()
for classes, since for structures the purpose of the change would lost during unboxing; in these
cases simply defer to the original reflection implementation).

TypeDescriptionProvider implementation

The job of the TypeDescriptionProvider is to return an ICustomTypeDescriptor that
describes the specified type/instance. As we are aiming at reflective classes we
can focus on types (not instances), and since we are using dynamic type creation
we want to re-use any generated classes. To do this we will simply cache a specific
ICustomTypeDescriptors for each type we are asked about. In order to get a starting
point we will again use chaining (this is supported on a base ctor overload) - i.e. we
could use the previously defined provider
for a given type. As a final measure, we will simply use the global provider - i.e.
the provider that is defined for "object".

ICustomTypeDescriptor implementation

Again, chaining to the rescue. We don't need to implement everything - just the bits we want to change.
Specifically, we'll ask the base descriptor about the properties *it* knows about, and then we'll inspect
them for something that smells like reflection:

Obviously this is only suited to types under our control, but is very expressive. It is not
necessary to include the attribute on sub-types since TypeDescriptor automatically
looks at ancestors to resolve a provider.

The second approach is via TypeDescriptor.AddProvider(). Again this supports
inheritance, but to make our lives easier (with chaining, etc.) we can expose a helper:

Performance

So how does it perform? How about we use runtime property access a great many times (to make
even the crudest timers reasonable) and see
how it behaves with and without the change (see sample). In particular, we will measure the time to execute:

For direct (hard-coded) access (against a single property for brevity):

property get

property set

event add/remove

Op count (as a check that everything happened)

For indirect (System.ComponentModel) access (against several properties, including inheritance):

First - note the OpCounts all match up before and after, so we are achieving the same amount of
useful work. GetValue on Name, for instance has gone from >10s to <100ms - in fact about 180 times faster.
For When there is an additional fixed cost from boxing, but still a 40-fold improvement.
More important, however, is the comparison to direct (compiled) access; we are nearly there!
Looking at the figures as a factor or direct compiled access gives ~7, ~1.5and ~1 for "get", "set" and "event" access, which
is very satisfactory (the latter being due to the fixed overhead of Delegate manipulations). Metadata (GetProperties) access
is a curiosity; on some machines it is faster, on some slower, so we'll call it even. Still, a vast improvement.

The real joy is you can apply this as sparingly or as liberally as you like; either apply it to that important class that you bind to in a grid, or apply to
System.Windows.Forms.Control and see what happens (I haven't tried this; one wonders
if it might improve the performance of Visual Studio, particularly the designer which
depends heavily on PropertyGrid and the System.ComponentModel). I would
definitely stop well short of applying it to object though.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.