예제 #1
0
        private void EmitMethod(
            AbstractTypeBuilderList builders, MethodInfo methdoInfo, BuildElement buildElement)
        {
            SetID(builders);

            _context.BuildElement = buildElement;

            bool isCatchBlockRequired   = false;
            bool isFinallyBlockRequired = false;

            foreach (IAbstractTypeBuilder builder in builders)
            {
                isCatchBlockRequired   = isCatchBlockRequired || IsApplied(builder, builders, BuildStep.Catch);
                isFinallyBlockRequired = isFinallyBlockRequired || IsApplied(builder, builders, BuildStep.Finally);
            }

            BeginEmitMethod(methdoInfo);

            Build(BuildStep.Begin, builders);

            EmitHelper emit        = _context.MethodBuilder.Emitter;
            Label      returnLabel = _context.ReturnLabel;

            // Begin catch block.
            //

            if (isCatchBlockRequired || isFinallyBlockRequired)
            {
                _context.ReturnLabel = emit.DefineLabel();
                emit.BeginExceptionBlock();
            }

            Build(BuildStep.Before, builders);
            Build(BuildStep.Build, builders);
            Build(BuildStep.After, builders);

            if (isCatchBlockRequired || isFinallyBlockRequired)
            {
                emit.MarkLabel(_context.ReturnLabel);
                _context.ReturnLabel = returnLabel;
            }

            // End catch block.
            //
            if (isCatchBlockRequired)
            {
                emit
                .BeginCatchBlock(typeof(Exception));

                _context.ReturnLabel = emit.DefineLabel();
                _context.Exception   = emit.DeclareLocal(typeof(Exception));

                emit
                .stloc(_context.Exception);

                Build(BuildStep.Catch, builders);

                emit
                .rethrow
                .end();

                emit.MarkLabel(_context.ReturnLabel);
                _context.ReturnLabel = returnLabel;
                _context.Exception   = null;
            }

            if (isFinallyBlockRequired)
            {
                emit.BeginFinallyBlock();
                _context.ReturnLabel = emit.DefineLabel();

                Build(BuildStep.Finally, builders);

                emit.MarkLabel(_context.ReturnLabel);
                _context.ReturnLabel = returnLabel;
            }

            if (isCatchBlockRequired || isFinallyBlockRequired)
            {
                emit.EndExceptionBlock();
            }

            Build(BuildStep.End, builders);

            EndEmitMethod();
        }