public static Type DynamicPointTypeGen()
{
Type pointType = null;
Type[] ctorParams = new Type[] {typeof(int), typeof(int), typeof(int)};
AppDomain myDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder pointModule = myAsmBuilder.DefineDynamicModule("PointModule", "Point.dll");
TypeBuilder pointTypeBld = pointModule.DefineType("Point", TypeAttributes.Public);
FieldBuilder xField = pointTypeBld.DefineField("x", typeof(int), FieldAttributes.Public);
FieldBuilder yField = pointTypeBld.DefineField("y", typeof(int), FieldAttributes.Public);
FieldBuilder zField = pointTypeBld.DefineField("z", typeof(int), FieldAttributes.Public);
Type objType = Type.GetType("System.Object");
ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);
ConstructorBuilder pointCtor = pointTypeBld.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, ctorParams);
ILGenerator ctorIL = pointCtor.GetILGenerator();
// NOTE: ldarg.0 holds the "this" reference - ldarg.1, ldarg.2, and ldarg.3
// hold the actual passed parameters. ldarg.0 is used by instance methods
// to hold a reference to the current calling object instance. Static methods
// do not use arg.0, since they are not instantiated and hence no reference
// is needed to distinguish them.
ctorIL.Emit(OpCodes.Ldarg_0);
// Here, we wish to create an instance of System.Object by invoking its
// constructor, as specified above.
ctorIL.Emit(OpCodes.Call, objCtor);
// Now, we'll load the current instance ref in arg 0, along
// with the value of parameter "x" stored in arg 1, into stfld.
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_1);
ctorIL.Emit(OpCodes.Stfld, xField);
// Now, we store arg 2 "y" in the current instance with stfld.
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_2);
ctorIL.Emit(OpCodes.Stfld, yField);
// Last of all, arg 3 "z" gets stored in the current instance.
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_3);
ctorIL.Emit(OpCodes.Stfld, zField);
// Our work complete, we return.
ctorIL.Emit(OpCodes.Ret);
// Now, let's create three very simple methods so we can see our fields.
string[] mthdNames = new string[] { "GetX", "GetY", "GetZ" };
foreach (string mthdName in mthdNames)
{
MethodBuilder getFieldMthd = pointTypeBld.DefineMethod(mthdName, MethodAttributes.Public, typeof(int), null);
ILGenerator mthdIL = getFieldMthd.GetILGenerator();
mthdIL.Emit(OpCodes.Ldarg_0);
switch (mthdName)
{
case "GetX": mthdIL.Emit(OpCodes.Ldfld, xField); break;
case "GetY": mthdIL.Emit(OpCodes.Ldfld, yField); break;
case "GetZ": mthdIL.Emit(OpCodes.Ldfld, zField); break;
}
mthdIL.Emit(OpCodes.Ret);
}
// Finally, we create the type.
pointType = pointTypeBld.CreateType();
// Let's save it, just for posterity.
//myAsmBuilder.Save("Point.dll");
return pointType;
}