Monday, November 20, 2006

DynamicClassFactory - Motivation

We are all familiar with Activator.CreateInstance. It's a great tool, which provides a simple way of dynamically instantiating an object that was unknown at design-time. An obvious us for is to support plug-ins in an application.
Yet Activator.CreateInstance has one huge drawback - it's sloooooooow! Performance has been significantly improved between .NET 1.1 and .NET 2.0, but still, it's on the order of 60 times slower than a simple call to "new" for a parameter-less constructor and up to 1000 times slower with a highly parameterized constructor. If you're instantiating an object once in a while, this has no meaning. Yet, if you need to instantiate a lot of such dynamically-defined objects, you need a better solution.

The DynamicClassFactory (DCF) comes to solve this exact problem. I have written it about 2 years ago, and intended to publish it on CodeProject ever since. Yet, I never find the time to do it. So I'll publish it here, on my blog, with the hope of one day writing a more elaborated article and publish it somewhere.

It's not perfect, and some parts need to be arranged, but that's what I'm currently using. I'd like to change the configuration part, and cleaning up some of the code (remove the id-based instantiation for example), but still - it's useful as it is.

The basic idea is as follows: every class you want to be supported by the DCF needs to be defined in the configuration file, including the paths where referenced libraries can be found. At run-time, the DCF reads all the constructors of these classes using Reflection and builds a helper class that knows how create the object with each of it constructors. All this is kept in a dynamically generated class, which given the parameters knows which helper class to call. You end up with a reference to this dynamically generated class, and creating an instance of an object becomes a simple (small) set of if-conditions and one "new" instantiation. The result is a performance of only 10 times slower than direct "new", regardless of the number of constructor parameters.

There will now be a set of 4 posts (including this one), which provide the complete code for the DCF. I don't have time to elaborate much - hope the code and comment suffice. Please let me know if you need any help...

Now let's begin.

First, let's look at the interface implemented by the dynamically generated class:


using System;

namespace DynamicClassFactory
{
public interface IClassFactory
{
object CreateInstance(int id, params object[] args);
}
}

Simple, right? This means that creating an object would be exactly the same as with Activator.CreateInstance.


To be continued in next post...

No comments: