From: Joe W. <joe...@us...> - 2002-10-07 00:08:05
|
Update of /cvsroot/mockobjects/nmock/src/NMock/Dynamic In directory usw-pr-cvs1:/tmp/cvs-serv28357/src/NMock/Dynamic Modified Files: ClassGenerator.cs Log Message: ClassGenerator can now create dynamic mocks based on classes as well as interfaces (although it can only override virtual methods). Index: ClassGenerator.cs =================================================================== RCS file: /cvsroot/mockobjects/nmock/src/NMock/Dynamic/ClassGenerator.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ClassGenerator.cs 6 Oct 2002 23:11:39 -0000 1.2 +++ ClassGenerator.cs 7 Oct 2002 00:08:02 -0000 1.3 @@ -10,47 +10,45 @@ { private static IDictionary boxingOpCodes; - public class GeneratedBase - { - private IMock underlyingMock; - - public IMock UnderlyingMock - { - set { underlyingMock = value; } - } - - protected object CallMock(string name, params object[] args) - { - return underlyingMock.Call(name, args); - } - } - 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); + implementMethod(type, typeBuilder, m, mockFieldBuilder); } Type proxyType = typeBuilder.CreateType(); - GeneratedBase result = (GeneratedBase)Activator.CreateInstance(proxyType); - result.UnderlyingMock = mock; + object result = Activator.CreateInstance(proxyType); + FieldInfo underlyingMock = proxyType.GetField("underlyingMock"); + underlyingMock.SetValue(result, mock); return result; } - private TypeBuilder getTypeBuilder(string name, Type implementsInterface) + 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"); - return moduleBuilder.DefineType(name, TypeAttributes.Public, typeof(GeneratedBase), - new Type[]{implementsInterface}); + 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) + private void implementMethod(Type type, TypeBuilder typeBuilder, MethodInfo m, FieldBuilder mockFieldBuilder) { Type returnType = m.ReturnType; ArrayList types = new ArrayList(); @@ -60,7 +58,6 @@ } Type[] paramTypes = (Type[])types.ToArray(typeof(Type)); MethodBuilder methodBuilder = typeBuilder.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.Virtual, returnType, paramTypes); - typeBuilder.DefineMethodOverride(methodBuilder, type.GetMethod(m.Name)); ILGenerator il = methodBuilder.GetILGenerator(); @@ -76,6 +73,7 @@ } 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)); @@ -98,9 +96,8 @@ } } - MethodInfo call = typeof(GeneratedBase).GetMethod("CallMock", - BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - il.EmitCall(OpCodes.Call, call, null); + MethodInfo call = typeof(IMock).GetMethod("Call"); + il.EmitCall(OpCodes.Callvirt, call, null); if (returnType == typeof(void)) { |