/// <summary>Generates an implementation of klass, if it is an interface, or a subclass of klass that delegates its virtual methods to a Lua table.</summary> public void GenerateClass(Type klass, out Type newType, out Type[][] returnTypes, LuaTable luaTable) { string typeName; lock (this) { typeName = "LuaGeneratedClass" + luaClassNumber; luaClassNumber++; } TypeBuilder myType; // Define a public class in the assembly, called typeName if (klass.IsInterface) { myType = newModule.DefineType(typeName, TypeAttributes.Public, typeof(object), new Type[] { klass, typeof(ILuaGeneratedType) }); } else { myType = newModule.DefineType(typeName, TypeAttributes.Public, klass, new Type[] { typeof(ILuaGeneratedType) }); } // Field that stores the Lua table FieldBuilder luaTableField = myType.DefineField("__luaInterface_luaTable", typeof(LuaTable), FieldAttributes.Public); // Field that stores the return types array FieldBuilder returnTypesField = myType.DefineField("__luaInterface_returnTypes", typeof(Type[][]), FieldAttributes.Public); // Generates the constructor for the new type, it takes a Lua table and an array // of return types and stores them in the respective fields ConstructorBuilder constructor = myType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(LuaTable), typeof(Type[][]) }); ILGenerator generator = constructor.GetILGenerator(); generator.Emit(OpCodes.Ldarg_0); if (klass.IsInterface) { generator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); } else { generator.Emit(OpCodes.Call, klass.GetConstructor(Type.EmptyTypes)); } generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Stfld, luaTableField); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldarg_2); generator.Emit(OpCodes.Stfld, returnTypesField); generator.Emit(OpCodes.Ret); // Generates overriden versions of the klass' public and protected virtual methods that have been explicitly specfied BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; MethodInfo[] classMethods = klass.GetMethods(flags); returnTypes = new Type[classMethods.Length][]; int i = 0; foreach (MethodInfo method in classMethods) { if (klass.IsInterface) { GenerateMethod(myType, method, MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot, i, luaTableField, returnTypesField, false, out returnTypes[i]); i++; } else if (!method.IsPrivate && !method.IsFinal && method.IsVirtual && luaTable.ContainsKey(method.Name)) { GenerateMethod(myType, method, (method.Attributes | MethodAttributes.NewSlot) ^ MethodAttributes.NewSlot, i, luaTableField, returnTypesField, true, out returnTypes[i]); i++; } } // Generates an implementation of the __luaInterface_getLuaTable method MethodBuilder returnTableMethod = myType.DefineMethod("__luaInterface_getLuaTable", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(LuaTable), new Type[0]); myType.DefineMethodOverride(returnTableMethod, typeof(ILuaGeneratedType).GetMethod("__luaInterface_getLuaTable")); generator = returnTableMethod.GetILGenerator(); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldfld, luaTableField); generator.Emit(OpCodes.Ret); // Creates the type newType = myType.CreateType(); }