Mass Producing Your Dynamic Types
The next step is to figure out how to instantiate your dynamic type. The simplest method (shown above) is to use reflection, using Activator.CreateInstance()
. But, there are a couple of problems with the reflection-based approach. First, there's no obvious way to instantiate an object with a non-default set of parameters. Also, you might be wary of the poor performance that's often associated with reflection (but more on that later).
An alternative to the reflection-based approach is to use the Prototype pattern. The idea here is to create new objects by copying a prototypical instance. The good news about using the prototype pattern is that it doesn't require any reflection at all. Here's the implementation:
readonly BinaryFormatter b
= new BinaryFormatter();
= new MemoryStream();
public object New()
The advantage of this pattern is that you only have to use Activator.CreateInstance
a single timeto create your initial prototype. After that, you can create new instances by "hydrating" a serialized copythat is, populating the properties of the serialized copy with values.
The bad news is that this particular prototype implementation uses serialization. This puts a constraint on the target class: It must be serializable.
Strategy #2: Building Dynamic Adapters
If dynamically subclassing an object seems way too easy, you've got good instincts. It turns out that subclassing a type to add an interface has at least three limitations:
- Methods of the base class must be explicitly marked as virtual.
- The base class has to be a class, and not a struct.
- The target class can't be sealed.
So what's the alternative to subclassing? One option is to dynamically build an object adapter
that wraps the target class, and implements the specified interface. My approach here was inspired by a really cool CodeProject article
by Rüdiger Klaehn called Autocaster.
Before you get into building more dynamic classes, take a look at the non-dynamic object adapter. The ShootableCameraAdapter wraps a Camera object to make it compatible with the IShootable interface:
public class ShootableCameraAdapter: IShootable
private Camera wrappedCamera;
public ShootableCameraAdapter (Camera camera)
this.wrappedCamera = camera;
public void Shoot()
looks convoluted, but it's not doing any rocket science. Really, it's just building a new type that implements the specified interface, and looping through the interface methods, adding a call to the wrapped object for each one. The only downside to this approach is that it doesn't pass the substitution test. That is, you can't substitute an instance of the wrapper type for an instance of the base type because they don't participate in an inheritance relationship.