On to choice 3 from my post a while ago.
Before finishing off the exercise… LEt’s talk a little bit about LWG. In .Net 2.0 you can create static function on the fly. Essentially you are building in IL (think assembly language) as set of instructions on the fly. You then can create a handle to the function you’ve created (called a delegate in .Net). And away you go.
I’m enclosing my sample code here in this post. In this sample I’m generating 2 functions. One that invokes a static method and one that creates an instance of a class and then invokes a method on it. In both cases we are not dealing with arguments on the method (for simplicity’s sake).
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
namespace LWG
{
class Program
{
static void Main(string[] args)
{
Sample sample = new Sample();
sample.Get(); Sample.StaticGet();
//These methods use LWG to generate a method and invoke it.
Method();
StaticMethod();
}
//Define the format of the function handle
public delegate void Dispatch();
static void Method()
{
//Get information about a constructor. Instead of hardcoding the type in production you could pass it in by name.
//This call is quick.
ConstructorInfo ctorInfo =
typeof(Sample).GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
Type.DefaultBinder,
new Type[] { },
null);
//Lookup information about a specific type.
MethodInfo mInfo = typeof(Sample).GetMethod("Get");
//Now build the static method.
DynamicMethod method = new DynamicMethod("SampleGetCall", null, null, typeof(Sample), true);
ILGenerator generator = method.GetILGenerator();
//Declare a local type of type "sample"
LocalBuilder local = generator.DeclareLocal(typeof(Sample));
// New the described object
generator.Emit(OpCodes.Newobj, ctorInfo);
//Store the object in the local type I created (I think that's what it is doing here)
generator.Emit(OpCodes.Stloc_0);
// Load the object to the top of the stack.
generator.Emit(OpCodes.Ldloc_0);
// call the method on the object
generator.Emit(OpCodes.Callvirt, mInfo);
//Finish the method
generator.Emit(OpCodes.Ret);
//Create a handle to the newly generated function
Dispatch dipatch = (Dispatch)method.CreateDelegate(typeof(Dispatch));
//Invoke it. (or you could keep it around)
dipatch.Invoke();
}
public static void StaticMethod()
{ //LWG
MethodInfo mInfo = typeof(Sample).GetMethod("StaticGet");
DynamicMethod method = new DynamicMethod("SampleStaticGetCall", null, null, typeof(Sample), true);
ILGenerator generator = method.GetILGenerator();
generator.Emit(OpCodes.Call, mInfo);
generator.Emit(OpCodes.Ret);
Dispatch dipatch = (Dispatch)method.CreateDelegate(typeof(Dispatch));
dipatch.Invoke();
}
}
class Sample
{
public Sample()
{
//Default Ctor
Console.WriteLine("Sample Ctor called.");
}
//SImulate the get method.
public void Get()
{
System.Console.WriteLine("Get invoked.");
}
public static void StaticGet()
{
Console.WriteLine("Static Get Called");
}
}
}