|
From: <sm...@us...> - 2003-01-03 16:00:51
|
Update of /cvsroot/nmock/nmock/src/NMock/Dynamic
In directory sc8-pr-cvs1:/tmp/cvs-serv13198/src/NMock/Dynamic
Modified Files:
ClassGenerator.cs
Log Message:
Extracted MethodImplementor and BoxingOpCodes from ClassGenerator
Index: ClassGenerator.cs
===================================================================
RCS file: /cvsroot/nmock/nmock/src/NMock/Dynamic/ClassGenerator.cs,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** ClassGenerator.cs 31 Dec 2002 21:36:38 -0000 1.5
--- ClassGenerator.cs 3 Jan 2003 16:00:47 -0000 1.6
***************
*** 9,13 ****
public class ClassGenerator
{
! private static IDictionary boxingOpCodes;
public virtual object Generate(Type type, IMock mock)
--- 9,14 ----
public class ClassGenerator
{
! private const System.Reflection.BindingFlags ALL_INSTANCE_METHODS
! = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
public virtual object Generate(Type type, IMock mock)
***************
*** 16,46 ****
}
! public virtual object Generate(Type type, IMock mock, IList methodsToIgnore)
! {
! methodsToIgnore.Add("Equals");
! methodsToIgnore.Add("ToString");
! TypeBuilder typeBuilder = getTypeBuilder("Mock" + type.Name, type);
! FieldBuilder mockFieldBuilder = typeBuilder.DefineField("underlyingMock", typeof(IMock), FieldAttributes.Public);
! MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
! foreach ( MethodInfo m in methods )
! {
! if (IsOverridable(m) && !methodsToIgnore.Contains(m.Name))
! {
! 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 bool IsOverridable(MethodInfo m)
{
return (m.IsVirtual && ! m.IsFinal);
}
! private TypeBuilder getTypeBuilder(string name, Type originalType)
{
AppDomain appDomain = AppDomain.CurrentDomain;
--- 17,44 ----
}
! public virtual object Generate(Type type, IMock mock, IList methodsToIgnore)
! {
! methodsToIgnore.Add("Equals");
! methodsToIgnore.Add("ToString");
!
! TypeBuilder typeBuilder = GetTypeBuilder("Mock" + type.Name, type);
! MethodImplementor methodImplementor = new MethodImplementor(typeBuilder);
!
! foreach ( MethodInfo methodInfo in type.GetMethods(ALL_INSTANCE_METHODS) )
! {
! if (IsOverridable(methodInfo) && !methodsToIgnore.Contains(methodInfo.Name))
! {
! methodImplementor.Implement(methodInfo);
! }
! }
! return CreateProxyInstance(typeBuilder, mock);
! }
!
! bool IsOverridable(MethodInfo m)
{
return (m.IsVirtual && ! m.IsFinal);
}
! TypeBuilder GetTypeBuilder(string name, Type originalType)
{
AppDomain appDomain = AppDomain.CurrentDomain;
***************
*** 64,170 ****
}
! 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;
! }
! }
! }
!
!
}
--- 62,233 ----
}
! object CreateProxyInstance(TypeBuilder typeBuilder, IMock mock)
! {
! Type proxyType = typeBuilder.CreateType();
! object result = Activator.CreateInstance(proxyType);
! FieldInfo underlyingMock = proxyType.GetField("underlyingMock");
! underlyingMock.SetValue(result, mock);
!
! return result;
! }
!
! }
!
! public class MethodImplementor
! {
! private BoxingOpCodes boxingOpCodes = new BoxingOpCodes();
! private TypeBuilder typeBuilder;
! private FieldBuilder mockFieldBuilder;
!
! public MethodImplementor(TypeBuilder aTypeBuilder)
! {
! typeBuilder = aTypeBuilder;
! mockFieldBuilder = typeBuilder.DefineField("underlyingMock", typeof(IMock), FieldAttributes.Public);
! }
!
! public virtual void Implement(MethodInfo methodInfo)
! {
! Type returnType = methodInfo.ReturnType;
! ParameterInfo[] parameterInfo = methodInfo.GetParameters();
! Type[] paramTypes = ExtractParameterTypes(parameterInfo);
! ILGenerator il = CreateILGenerator(methodInfo, returnType, paramTypes);
!
! EmitMethodSignature(methodInfo, paramTypes, il);
! EmitMethodCall(il);
! EmitMethodReturn(returnType, il);
! }
!
! private Type[] ExtractParameterTypes(ParameterInfo[] parameters)
! {
! Type[] paramTypes = new Type[parameters.Length];
! for (int i = 0; i < parameters.Length; ++i)
! {
! paramTypes[i] = parameters[i].ParameterType;
! }
! return paramTypes;
! }
!
! private ILGenerator CreateILGenerator(MethodInfo methodInfo, Type returnType, Type[] paramTypes)
! {
! MethodBuilder methodBuilder =
! typeBuilder.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, returnType, paramTypes);
!
! return methodBuilder.GetILGenerator();
! }
!
! private void EmitMethodSignature(MethodInfo methodInfo, Type[] paramTypes, ILGenerator il)
! {
! foreach (Type paramType in paramTypes)
! {
! il.DeclareLocal(paramType);
! }
! il.Emit(OpCodes.Ldarg_0);
! il.Emit(OpCodes.Ldfld, mockFieldBuilder);
! il.Emit(OpCodes.Ldstr, StripGetSetPrefix(methodInfo));
! 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);
! }
! }
! }
!
! private void EmitMethodCall(ILGenerator il)
! {
! MethodInfo call = typeof(IMock).GetMethod("Call");
! il.EmitCall(OpCodes.Callvirt, call, null);
! }
! private void EmitMethodReturn(Type returnType, ILGenerator il)
! {
! if (returnType == typeof(void))
! {
! il.Emit(OpCodes.Pop);
! }
! else
! {
! if (returnType.IsPrimitive)
! {
! il.Emit(OpCodes.Unbox, returnType);
! il.Emit(boxingOpCodes[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);
! }
! private string StripGetSetPrefix(MethodInfo methodInfo)
! {
! string methodName;
! methodName = methodInfo.Name;
! if (methodName.StartsWith("get_") || methodName.StartsWith("set_"))
! {
! methodName = methodName.Substring(4);
! }
! return methodName;
! }
! }
! public class BoxingOpCodes
! {
! private static IDictionary boxingOpCodes;
! public OpCode this[Type aType]
! {
! get
! {
! return GetOpCode(aType);
! }
! }
!
! private static OpCode GetOpCode( 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;
! }
! }
! }
}
|