From: <gc...@us...> - 2002-10-12 03:29:56
|
Update of /cvsroot/dotnetmock/dotnetmock/DotNetMock/Dynamic/Generate In directory usw-pr-cvs1:/tmp/cvs-serv12370/DotNetMock/Dynamic/Generate Added Files: ClassGenerator.cs Log Message: Added the dynamic Mock Object Generation package --- NEW FILE: ClassGenerator.cs --- using System; using System.Collections; using System.Reflection; using System.Reflection.Emit; namespace DotNetMock.Dynamic.Generate { public class ClassGenerator { private static IDictionary boxingOpCodes; public object Generate(Type type, IMock mock) { TypeBuilder typeBuilder = getTypeBuilder("Mock" + type.Name, type); FieldBuilder mockFieldBuilder = typeBuilder.DefineField("underlyingMock", typeof(IMock), FieldAttributes.Public); MethodInfo[] methods = type.GetMethods(); foreach ( MethodInfo m in methods ) { implementMethod(type, typeBuilder, m, mockFieldBuilder); } Type proxyType = typeBuilder.CreateType(); object result = Activator.CreateInstance(proxyType); FieldInfo underlyingMock = proxyType.GetField("underlyingMock"); underlyingMock.SetValue(result, mock); return result; } private TypeBuilder getTypeBuilder(string name, Type originalType) { AppDomain appDomain = AppDomain.CurrentDomain; AssemblyName assemblyName = new AssemblyName(); assemblyName.Name = "DynamicMockAssembly"; AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MockModule"); Type superClass; Type[] interfaces; if (originalType.IsInterface) { superClass = null; interfaces = new Type[] {originalType}; } else { superClass = originalType; interfaces = new Type[0]; } return moduleBuilder.DefineType(name, TypeAttributes.Public, superClass, interfaces); } private void implementMethod(Type type, TypeBuilder typeBuilder, MethodInfo m, FieldBuilder mockFieldBuilder) { Type returnType = m.ReturnType; ArrayList types = new ArrayList(); foreach (ParameterInfo param in m.GetParameters()) { types.Add(param.ParameterType); } Type[] paramTypes = (Type[])types.ToArray(typeof(Type)); MethodBuilder methodBuilder = typeBuilder.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.Virtual, returnType, paramTypes); ILGenerator il = methodBuilder.GetILGenerator(); foreach (ParameterInfo param in m.GetParameters()) { il.DeclareLocal(param.ParameterType); } string methodName = m.Name; if (methodName.StartsWith("get_") || methodName.StartsWith("set_")) { methodName = methodName.Substring(4); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, mockFieldBuilder); il.Emit(OpCodes.Ldstr, methodName); il.Emit(OpCodes.Ldc_I4_S, paramTypes.Length); il.Emit(OpCodes.Newarr, typeof(object)); if (paramTypes.Length > 0) { il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Ldloc_0); for(int i = 0; i < paramTypes.Length; i++) { il.Emit(OpCodes.Ldc_I4_S, i); il.Emit(OpCodes.Ldarg_S, i + 1); if (paramTypes[i].IsPrimitive) { il.Emit(OpCodes.Box, paramTypes[i]); } il.Emit(OpCodes.Stelem_Ref); il.Emit(OpCodes.Ldloc_0); } } MethodInfo call = typeof(IMock).GetMethod("Call"); il.EmitCall(OpCodes.Callvirt, call, null); if (returnType == typeof(void)) { il.Emit(OpCodes.Pop); } else { if (returnType.IsPrimitive) { il.Emit(OpCodes.Unbox, returnType); il.Emit(GetBoxingOpCode(returnType)); } il.DeclareLocal(returnType); il.Emit(OpCodes.Stloc_0); Label l = il.DefineLabel(); il.Emit(OpCodes.Br_S, l); il.MarkLabel(l); il.Emit(OpCodes.Ldloc_0); } il.Emit(OpCodes.Ret); } public OpCode GetBoxingOpCode( Type aType ) { if (boxingOpCodes == null) { boxingOpCodes = new Hashtable(); boxingOpCodes[typeof(sbyte)] = OpCodes.Ldind_I1; boxingOpCodes[typeof(short)] = OpCodes.Ldind_I2; boxingOpCodes[typeof(int)] = OpCodes.Ldind_I4; boxingOpCodes[typeof(long)] = OpCodes.Ldind_I8; boxingOpCodes[typeof(byte)] = OpCodes.Ldind_U1; boxingOpCodes[typeof(ushort)] = OpCodes.Ldind_U2; boxingOpCodes[typeof(uint)] = OpCodes.Ldind_U4; boxingOpCodes[typeof(ulong)] = OpCodes.Ldind_I8; boxingOpCodes[typeof(float)] = OpCodes.Ldind_R4; boxingOpCodes[typeof(double)] = OpCodes.Ldind_R8; boxingOpCodes[typeof(char)] = OpCodes.Ldind_U2; boxingOpCodes[typeof(bool)] = OpCodes.Ldind_I1; } if (boxingOpCodes.Contains(aType)) { return (OpCode)boxingOpCodes[aType]; } else { return OpCodes.Ldind_I1; } } } } |