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))
{
|