Lightweight Code Generation
Lightweight Code Generation and Reflection.Emit are one of my favorite features allowing me to extend the C# language in ways.
Fast Late Binding
Joel Pobar has a post from last year on hot to use Dynamic Methods (part of Lightweight Code Generation) to create extremely fast late bounded methods calls that approach the performance of early bounded calls. Calling a dynamic methods is orders faster than using Reflection and calling Delegate.DynamicInvoke.
Proxies and Patterns
Indigo allows one to create a proxy to a service by calling.
IFoo proxy = ProxyFactory.CreateProxy<IFoo>(“serviceUrl”);
where IFoo is a predeclared interface that describes a service contract.
One could use Reflection.Emit automatically to create a similar late-bound interface, which I’ll call patterns, on any object that supports methods of that interface.
IPattern pattern = PatternCaster.Cast<IPattern>(obj).
If obj derives from the IPattern interface, than obj is returned. Otherwise, a new proxy object wraps the original object and implements the IPattern interface, which maps calls to interface methods to the corresponding methods of the original object. There’s a one-time hit the first time code is generated for each type through the use of reflection.
In addition to late-binding, these patterns could allow support for static methods, which is not possible with interfaces normally. These patterns could also be used to support covariance and contravariance (with runtime checks) as well as conversions from non-generic interfaces to generic versions (and vice-versa). For example, an object of type T that supports IComparable could be dynamically cast to IComparable<T>. Another object that supports IComparable<T> could be dynamically cast to IComparable<object>.
Some other proxies that one could create are synchronized interfaces, broadcast interfaces (sort of like MulticastDelegates) or other interfaces that make an additional entry and exit call.
Multiple Dispatch Methods
Lightweight code generation could allow methods to be dispatched based on the runtime types of its parameters rather than the static compile-time types.
delegate T DoubleDispatch<T>(object x, object y);
DoubleDispatch<T> method = DoubleDispatchFactory.Create<T>(Type declaringType, methodName);
If there are multiple methods called methodName each with a different signature, method will check the type of each of its parameter, perform a hash lookup of the appropriate method, and call it after casting each parameter to the proper type accordingly. This is something that currently requires a a very slow call to Delegate.DynamicInvoke or Reflection in .NET v1.1. Double dispatch could also be used to simplify the creation of Visitor Design Pattern.
T t = MixinCreator.Create<T,M>() where M : struct;
What a function like this could do is dynamically generate code fore a new class that inherits from T and includes a new private field member, “m,” of type M. The new type would implement all the interfaces defined by M and redirect calls to methods of these interfaces to the corresponding interface methods in field member “m”. Also, abstract methods of T could be mapped to corresponding methods in M of the same name. Code generation would only occur once for each combination of T and M.
UPDATE: Mixins and the Patterns can’t actually be done through LCG, which can only create static Dynamic Methods, and require instead the use of Reflection.Emit, which is okay except that the new types can’t be freed during the lifetime of the application.
My own prior use of DynamicMethods has been limited to Pobar’s example above, and a simple dynamic method casting enum generic type parameter to int and vice-versa. I thought that I would take advantage of my break this month to explore some of the possibilities of Reflection.Emit that I thought up to simplify my C# programming.
I’ll provide examples of each of these cases in future posts.