Late Binding in C# using Dynamic Compilation
If you talk to my colleagues, you'll find out how much I really like reflection in .NET. I have a number of pet projects and unit tests that do things with reflection that are fairly extreme.
For example, I have a utility method in our unit tests called ImageCommandForEach that given a delegate will find every concrete class that descends from ImageCommand in our generated assemblies and will execute a delegate on a newly constructed instance of each command. Using this tool, I've written unit tests that tweak each command if needed, then apply the command to each supported pixel format and check for consistency in previous runs. This ensures that our image commands are stable.
Also in our code, we have a task where we will use our JPEG2000 and JBIG2 encoders if and only if the assembly is present and the application has been licensed to use them. The problem is that we can't just put in a reference, because that enforces a dependency and will require a license check. This is bad because it would penalize our customers who haven't licensed these codecs or just don't want to use them.
To solve this problem, we use reflection - we load the assemblies if they're there and construct the codecs if they're licensed, then we use them via reflection. The trouble with this approach is that it creates code that's hard to read - it gets bogged down with ConstructorInfo object and MethodInfo objects and so on and so forth.
My initial approach to this was to write a set of classes that would be friendly to this approach. I wrote a class called MethodWrapper which would hide all of the reflection and provide access to a delegate which has the same signature as MethodInfo.Invoke:
public delegate object MethodInvoker(object obj, object[] parameters);
Then I could write an object that looks like this:
class MyEncoderAdapter {
private object _obj;
private MethodWrapper _save;
public MyEncoderAdapter(Type t) {
_obj = new ConstructorWrapper(t, null).Make(null);
_save = new MethodWrapper(t, "Save", new object[] { typeof(Stream), typeof(AtalaImage), typeof(ProgressEventHandler) } );
}
public int Save(Stream stm, AtalaImage image, ProgressEventHandler handler)
{
_save.Call(_obj, stm, image, handler);
}
}
What this does is ConstructorWrapper makes an object that wraps a reflected ConstructorInfo object and exposes its Invoke method through the Make field. The constructor of MyEncoderAdapter, makes the type passed and and saves it in _obj. _save is a wrapper method that can invoke the Save method in the constructed object.
Now it uses MyEncoderAdapter and the code becomes far easier to read and maintain. Win - win.
The problem is that it is not performant code. MethodInfo.Invoke is slow. Fortunately, codecs don't get called often so this performance hit is not so bad. But I wanted to make sure that if someone used the adapters that in a situation that was performance critical that they'd be efficient. After reading this blog article by Rick Strahl, I saw a solution.
The trick is to define a pure abstract class that defines all the methods that you need to call in your dynamically loaded class. ie,
public abstract EncoderAdapter {
public abstract int Save(Stream stm, AtalaImage image, ProgressEventHandler handler);
}
Then you pass this type into a compiler with the type of the target class. The compiler will write a new class that descends from EncoderAdapter and it will implement all the abstract methods, passing them off to the target class - and it will write all of the code on the fly and let .NET turn the CLI into a performant executable. Lost yet? Yeah, me too. Let me show you how it would be used:
Type targetEncoder = GetTargetEncoderFromLoadedAssembly();
AdapterCompiler compiler = new AdapterCompiler();
AdapterFactory<EncoderAdapter> factory = compiler.DefineAdapter<EncoderAdapter>(targetEncoder);
EncoderAdapter encoder = factory.Construct(null);
encoder.Save(outputStream, image, null);
Here's what happens - GetTargetEncoderFromLoadedAssembly() loads an assembly and pulls out a Type that I care about. Then I make an AdapterCompiler that when I call DefineAdapter will make a new subclass of EncoderAdapter and it will map the Save method onto the Save method in targetEncoder. It does this by writing CLI code to call the method directly instead of using MethodInfo.Invoke.
Then to actually instantiate this, factory.Construct will call the constructor of the dynamic class which in turn will instantiate a targetEncoder and pass it the arguments. The resulting object can be used directly as if it were an EncoderAdapter.
The AdapterCompiler also works for abstract properties - they're really not that different from methods anyway. I'm attaching the entire project and source to this blog so you can look at it. In addition to working with generics to make the compiler and factory type strong, I also had a little fun working with LINQ. For example, I wanted to get all the methods in a Type that were abstract. I did this with a one-liner:
IEnumerable<MethodInfo> methods = abstractType.GetMethods().Where(mi => mi.IsAbstract);
There is a further application of this technology which I haven't tried yet, but seems pretty straight forward: middle-class multiple inheritance. .NET has the notion of pauper's multiple inheritance through interfaces. You can define the interface signature of an object then you can implement as many interfaces as you'd like in one object. The problem is that if you have a common behavior that you'd like multiple objects to have, then you'd need to either reimplement that behavior in each object (bad) or make one object that implements the behavior you want and then have multiple objects contain that object and delegate their interfaces to that object. Wait a minute - we have an object to auto delegate behaviors, so I should be able to extend my adapter compiler to be such that I can give it a list of types and it will either implement interfaces or abstract methods that perform the operations. Further, they can define conversion operators that would let you use the compiled object where you would use one of its constituent classes.
I call this middle-class multiple inheritance because while you could do this:
abstract class Foo : A {
public abstract methodOnB();
}
and compile this such that a B is also attached in to the dynamic class.
I could do this:
Foo f = factory.Construct(null);
A a = (A)f; // works - direct inheritance
B b = (B)f; // works - op_Explicit would do this for you
Foo x = (Foo)b; // fails - b is not really f - it's a part within f
So it's not truly multiple inheritance in the C++ sense, but it would get you a lot closer in a very practical way.
Zipped Project of the AdapterCompiler