예제 #1
0
        /// <summary>
        /// Emit the required IL instructions to the new method.
        /// </summary>
        private DynamicMethod BuildTestMethod(Type fixtureType, string methodName, MethodBodyReader reader)
        {
            Type            exceptionType                      = typeof(Exception);
            Type            exceptionCollectionType            = typeof(Dictionary <int, Exception>);
            ConstructorInfo exceptionCollectionTypeConstructor = exceptionCollectionType.GetConstructor(Type.EmptyTypes);
            MethodInfo      exceptionCollectionTypeAddMethod   = exceptionCollectionType.GetMethod("Add");

            List <List <ILInstruction> > sections = GetMethodSections(reader);
            ushort freeLocalIndex           = reader.GetFreeLocalIndex();
            ushort localExceptionCollection = freeLocalIndex++;
            ushort localException           = freeLocalIndex++;

            DynamicMethod testMethod = new DynamicMethod(methodName, exceptionCollectionType,
                                                         new Type[] { fixtureType }, fixtureType);
            ILGenerator generator = testMethod.GetILGenerator();

            DeclareLocalVariableTypes(generator, reader);

            // Instantiate exception collection.
            generator.DeclareLocal(exceptionCollectionType);
            generator.Emit(OpCodes.Nop);
            generator.Emit(OpCodes.Newobj, exceptionCollectionTypeConstructor);
            generator.Emit(OpCodes.Stloc_S, localExceptionCollection);

            foreach (List <ILInstruction> sect in sections)
            {
                // Start the try block.
                generator.BeginExceptionBlock();
                foreach (ILInstruction instruction in sect)
                {
                    instruction.EmitTo(generator);
                }
                // If no exception was thrown add a null reference to the collection.
                generator.Emit(OpCodes.Ldloc_S, localExceptionCollection);
                generator.Emit(OpCodes.Ldc_I4, sect[0].Offset);
                generator.Emit(OpCodes.Ldnull);
                generator.Emit(OpCodes.Callvirt, exceptionCollectionTypeAddMethod);
                generator.Emit(OpCodes.Nop);
                // Catch Exception.
                generator.BeginCatchBlock(exceptionType);
                // Save thrown exception.
                generator.DeclareLocal(exceptionType);
                generator.Emit(OpCodes.Stloc_S, localException);
                generator.Emit(OpCodes.Nop);
                // Add the exception to the collection.
                generator.Emit(OpCodes.Ldloc_S, localExceptionCollection);
                generator.Emit(OpCodes.Ldc_I4, sect[0].Offset);
                generator.Emit(OpCodes.Ldloc_S, localException);
                generator.Emit(OpCodes.Callvirt, exceptionCollectionTypeAddMethod);
                generator.Emit(OpCodes.Nop);
                // Exit the try block.
                generator.EndExceptionBlock();
            }
            generator.Emit(OpCodes.Ldloc_S, localExceptionCollection);
            generator.Emit(OpCodes.Ret);

            return(testMethod);
        }