|
From: Owen R. <exo...@us...> - 2004-06-23 04:45:01
|
Update of /cvsroot/nmock/nmock/src/NMock/Dynamic In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3533/src/NMock/Dynamic Modified Files: ClassGenerator.cs Added Files: BoxingOpCodes.cs MockTypeIdentifier.cs Log Message: committing jim's new fixes for increasing performance and reducing memory requirements --- NEW FILE: MockTypeIdentifier.cs --- using System; using System.Collections; namespace NMock.Dynamic { public class MockTypeIdentifier { Type typeToMock; IList methodsToIgnore; public MockTypeIdentifier(Type typeToMock, IList methodsToIgnore) { this.typeToMock = typeToMock; this.methodsToIgnore = new ArrayList(); for(int i = 0; i < methodsToIgnore.Count; i++) { this.methodsToIgnore.Add(methodsToIgnore[i]); } } public override bool Equals(object obj) { MockTypeIdentifier other = obj as MockTypeIdentifier; if(other == null) { return false; } if(other.typeToMock == this.typeToMock && ListEquals(this.methodsToIgnore, other.methodsToIgnore)) { return true; } return false; } public override int GetHashCode() { return typeToMock.GetHashCode() ^ methodsToIgnore.Count; //Lame, but simple } private bool ListEquals(IList listA, IList listB) { if(listA.Count != listB.Count) { return false; } for(int i = 0; i < listA.Count; i++) { if(listA[i] != listB[i]) { return false; } } return true; } } } Index: ClassGenerator.cs =================================================================== RCS file: /cvsroot/nmock/nmock/src/NMock/Dynamic/ClassGenerator.cs,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** ClassGenerator.cs 17 Jun 2004 05:13:38 -0000 1.21 --- ClassGenerator.cs 23 Jun 2004 04:44:53 -0000 1.22 *************** *** 6,16 **** namespace NMock.Dynamic { ! ! public class ClassGenerator { public const string INVOCATION_HANDLER_FIELD_NAME = "_invocationHandler"; ! internal const System.Reflection.BindingFlags ALL_INSTANCE_METHODS ! = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; readonly protected Type type; --- 6,14 ---- namespace NMock.Dynamic { ! public class ClassGenerator { public const string INVOCATION_HANDLER_FIELD_NAME = "_invocationHandler"; ! internal const System.Reflection.BindingFlags ALL_INSTANCE_METHODS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; readonly protected Type type; *************** *** 19,27 **** readonly protected Type superclassIfTypeIsInterface; ! public ClassGenerator(Type type, IInvocationHandler handler) ! : this(type, handler, new ArrayList()) {} ! public ClassGenerator(Type type, IInvocationHandler handler, IList methodsToIgnore) ! : this(type, handler, methodsToIgnore, null) {} public ClassGenerator(Type type, IInvocationHandler handler, IList methodsToIgnore, Type superclassIfTypeIsInterface) --- 17,27 ---- readonly protected Type superclassIfTypeIsInterface; ! static ModuleBuilder moduleBuilder; ! static Hashtable mockCache = new Hashtable(); ! static int typeCounter = 0; ! public ClassGenerator(Type type, IInvocationHandler handler) : this(type, handler, new ArrayList()) {} ! ! public ClassGenerator(Type type, IInvocationHandler handler, IList methodsToIgnore) : this(type, handler, methodsToIgnore, null) {} public ClassGenerator(Type type, IInvocationHandler handler, IList methodsToIgnore, Type superclassIfTypeIsInterface) *************** *** 35,72 **** public virtual object Generate() { ! methodsToIgnore.Add("Equals"); ! methodsToIgnore.Add("ToString"); ! methodsToIgnore.Add("Finalize"); ! TypeBuilder typeBuilder = CreateTypeBuilder(); ! MethodImplementor methodImplementor = ! new MethodImplementor(typeBuilder, DefineInvocationHandlerField(typeBuilder)); ! ImplementMethods(methodImplementor); ! return CreateProxyInstance(typeBuilder.CreateType()); } ! TypeBuilder CreateTypeBuilder() { ! AppDomain appDomain = AppDomain.CurrentDomain; ! AssemblyName assemblyName = new AssemblyName(); ! assemblyName.Name = "DynamicProxyAssembly"; ! AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ! ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MockModule"); ! return moduleBuilder.DefineType(ProxyClassName, TypeAttributes.Public, ProxySuperClass, ProxyInterfaces); } private FieldBuilder DefineInvocationHandlerField(TypeBuilder typeBuilder) { ! return typeBuilder.DefineField( ! ClassGenerator.INVOCATION_HANDLER_FIELD_NAME, ! typeof(IInvocationHandler), FieldAttributes.Public); } ! private void ImplementMethods(MethodImplementor methodImplementor) { foreach (Type currentType in new InterfaceLister().List(type)) { ! foreach ( MethodInfo methodInfo in currentType.GetMethods(ALL_INSTANCE_METHODS) ) { if (ShouldImplement(methodInfo)) --- 35,112 ---- public virtual object Generate() { ! IgnoreMethod("Equals"); ! IgnoreMethod("ToString"); ! IgnoreMethod("Finalize"); ! return CreateProxyInstance(GetMockType()); ! } ! private void IgnoreMethod(string method) ! { ! if(!methodsToIgnore.Contains(method)) ! { ! methodsToIgnore.Add(method); ! } } ! private Type GetMockType() { ! MockTypeIdentifier typeIdentifier = new MockTypeIdentifier(this.type, this.methodsToIgnore); ! ! Type mockType = (Type)mockCache[typeIdentifier]; ! ! if(mockType == null) ! { ! TypeBuilder typeBuilder = CreateTypeBuilder(); ! ! ImplementMethods(typeBuilder); ! ! mockType = typeBuilder.CreateType(); ! ! mockCache[typeIdentifier] = mockType; ! } ! ! return mockType; ! } ! ! private TypeBuilder CreateTypeBuilder() ! { ! if(moduleBuilder == null) ! { ! AppDomain appDomain = AppDomain.CurrentDomain; ! AssemblyName assemblyName = new AssemblyName(); ! assemblyName.Name = "DynamicProxyAssembly"; ! AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ! moduleBuilder = assemblyBuilder.DefineDynamicModule("MockModule"); ! } ! ! TypeBuilder builder = moduleBuilder.DefineType(ProxyClassName, TypeAttributes.Public, ProxySuperClass, ProxyInterfaces); ! ! return builder; ! } ! ! private object CreateProxyInstance(Type proxyType) ! { ! object result = Activator.CreateInstance(proxyType); ! ! FieldInfo handlerField = proxyType.GetField(INVOCATION_HANDLER_FIELD_NAME); ! handlerField.SetValue(result, handler); ! ! return result; } private FieldBuilder DefineInvocationHandlerField(TypeBuilder typeBuilder) { ! return typeBuilder.DefineField(INVOCATION_HANDLER_FIELD_NAME, typeof(IInvocationHandler), FieldAttributes.Public); } ! private void ImplementMethods(TypeBuilder typeBuilder) { + FieldBuilder handlerFieldBuilder = DefineInvocationHandlerField(typeBuilder); + MethodImplementor methodImplementor = new MethodImplementor(typeBuilder, handlerFieldBuilder); + foreach (Type currentType in new InterfaceLister().List(type)) { ! foreach ( MethodInfo methodInfo in currentType.GetMethods(ALL_INSTANCE_METHODS) ) { if (ShouldImplement(methodInfo)) *************** *** 80,144 **** private bool ShouldImplement(MethodInfo methodInfo) { ! if ( (! methodInfo.IsVirtual) || methodInfo.IsFinal || methodInfo.IsAssembly) { ! methodsToIgnore.Add(methodInfo.Name); } return ! methodsToIgnore.Contains(methodInfo.Name); } ! private object CreateProxyInstance(Type proxyType) { ! object result = Activator.CreateInstance(proxyType); ! ! FieldInfo handlerField = proxyType.GetField(INVOCATION_HANDLER_FIELD_NAME); ! handlerField.SetValue(result, handler); ! ! return result; } - - public string ProxyClassName { get { return "Proxy" + type.Name; } } - public Type ProxySuperClass { get { return type.IsInterface ? superclassIfTypeIsInterface : type; } } - public Type[] ProxyInterfaces { get { return type.IsInterface ? new Type[] { type } : new Type[0]; } } - } - - 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; ! } } } ! } --- 120,143 ---- private bool ShouldImplement(MethodInfo methodInfo) { ! if ((!methodInfo.IsVirtual) || methodInfo.IsFinal || methodInfo.IsAssembly) { ! IgnoreMethod(methodInfo.Name); } return ! methodsToIgnore.Contains(methodInfo.Name); } ! public string ProxyClassName { ! get { return "Proxy" + type.Name + "_" + typeCounter++; } } ! public Type ProxySuperClass { ! get { return type.IsInterface ? superclassIfTypeIsInterface : type; } } ! public Type[] ProxyInterfaces { ! get { return type.IsInterface ? new Type[] { type } : new Type[0]; } } } ! } \ No newline at end of file --- NEW FILE: BoxingOpCodes.cs --- using System; using System.Collections; using System.Reflection.Emit; namespace NMock.Dynamic { 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; } } } } |