/// <summary>
        /// Emits a catch block to return an <see cref="IActionResult"/>
        /// for a given <see cref="ExceptionHandlerAttribute"/>.
        /// </summary>
        /// <param name="methodIL">An IL Generator.</param>
        /// <param name="attr">Amn <see cref="ExceptionHandlerAttribute"/>.</param>
        /// <param name="localResponse">A local to receive the <see cref="IActionResult"/>.</param>
        private void EmitCatchBlock(IEmitter methodIL, ExceptionHandlerAttribute attr, ILocal localResponse)
        {
            methodIL.DeclareLocal(attr.ExceptionType, out ILocal localEx);

            methodIL.BeginCatchBlock(attr.ExceptionType);
            methodIL.Emit(OpCodes.Stloc_S, localEx);

            // Write out the exception
            methodIL.EmitWriteLine(localEx);

            if (attr.ModelType != null)
            {
                methodIL
                .DeclareLocal(attr.ModelType, out ILocal localModel)
                .EmitModelBinder(localEx, localModel)
                .EmitStatusCodeCall(attr.StatusCode, localModel, localResponse);
            }
            else
            {
                methodIL.EmitStatusCodeCall(attr.StatusCode, localResponse);
            }
        }
        /// <summary>
        /// Builds the method.
        /// </summary>
        /// <returns>The built method.</returns>
        public IMethodBuilder BuildMethod()
        {
            string name = this.methodInfo.Name;

            MethodAttributes attrs = this.methodInfo.Attributes & ~MethodAttributes.Abstract;

            var methodBuilder = this.context
                                .TypeBuilder
                                .NewMethod(this.methodInfo.Name)
                                .MethodAttributes(attrs)
                                .CallingConvention(CallingConventions.HasThis)
                                .Returns <IActionResult>();

            if (this.methodParmAttrs.Any() == true)
            {
                this.BuildParameters(methodBuilder, this.methodParmAttrs);
            }
            else
            {
                this.BuildParameters(methodBuilder, this.methodParms);
            }

            if (methodBuilder.ResolveMvcAttributes(this.methodInfo) == false)
            {
                methodBuilder.ResolveHttpControllerEndPointAttribute(this.methodInfo);
            }

            methodBuilder.ProcessAttributes(this.methodInfo);

            Type returnModelType   = this.methodInfo.ReturnType;
            int  successStatusCode = 200;
            int  failStatusCode    = 500;
            var  responseAttr      = this.methodInfo.GetCustomAttribute <HttpResponseAttribute>();

            if (responseAttr != null)
            {
                successStatusCode = responseAttr.SuccessStatusCode;
                failStatusCode    = responseAttr.FailureStatusCode;
                returnModelType   = responseAttr.ModelType;
            }

            MethodInfo serviceMethod = this.context.BaseType.GetMethod(name, this.methodArgs);

            // Emit Method IL
            IEmitter methodIL = methodBuilder.Body();

            methodIL.DeclareLocal <IActionResult>("actionResponse", out ILocal localResponse);
            ILocal localReturnValue = null;

            // Does the method return any data?
            if (this.methodInfo.ReturnType != typeof(void))
            {
                methodIL.DeclareLocal(serviceMethod.ReturnType, "returnValue", out localReturnValue);
            }

            methodIL
            .DeclareLocal <Exception>("exception", out ILocal localEx)
            .DeclareLocal <Controller>("controller", out ILocal localController)
            .DeclareLocal <IServiceProvider>("services", out ILocal localServices)
            .DefineLabel("endMethod", out ILabel endMethod)

            // Store Controller reference
            .Comment("== Load and store controller ==")
            .LdArg0()
            .StLoc(localController)

            // Get Services
            .Comment("== Load and store request service provider ==")
            .LdArg0()
            .CallVirt(RequestPropertyInfo.GetGetMethod())
            .CallVirt(HttpContextPropertyInfo.GetGetMethod())
            .CallVirt(RequestServicesPropertyInfo.GetGetMethod())
            .StLoc(localServices);

            // Check for service calls.
            var serviceCallEmitter = new ServiceCallFilterEmitter(this.methodInfo.DeclaringType, methodIL);

            serviceCallEmitter.EmitExecuting(localController, localServices, localResponse);

            methodIL
            .LdLoc(localResponse)
            .BrTrue(endMethod)
            .Try()
            .Comment("== Service Method Call ==");

            this.EmitServiceMethodCall(
                methodIL,
                serviceMethod);

            if (localReturnValue != null)
            {
                methodIL
                .StLoc(localReturnValue)

                .EmitIfNotNull(
                    localReturnValue,
                    (il) =>
                {
                    il.EmitWriteLine("**************** SUCCESS *****************");
                    il.EmitStatusCodeCall(successStatusCode, localReturnValue, localResponse);
                },
                    (il) =>
                {
                    il.EmitWriteLine("**************** FAIL *****************");
                    il.EmitStatusCodeCall(failStatusCode, null, localResponse);
                });
            }
            else
            {
                methodIL.EmitStatusCodeCall(successStatusCode, localResponse);
            }

            if (this.EmitCatchBlocks(methodIL, localResponse) == false)
            {
                methodIL.BeginCatchBlock(typeof(Exception));
                methodIL.Emit(OpCodes.Stloc_S, localEx);

                methodIL.EmitWriteLine("--------------- EXCEPTION --------------");
                methodIL.EmitWriteLine(localEx);

                methodIL.EmitStatusCodeCall(StatusCodes.Status500InternalServerError, localResponse);
            }

            methodIL
            .Finally();

            // Emit Service Call Attribute Executed calls.
            serviceCallEmitter.EmitExecuted(localController, localServices, localResponse);

            methodIL
            .EndExceptionBlock()

            .MarkLabel(endMethod)

            .Comment("== Load Response ==")
            .LdLoc(localResponse)
            .Ret();

            return(methodBuilder);
        }