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;
}
}
}
}
|