private void HandleMethods(
            TypeBuilder typeBuilder,
            Type interfaceType,
            FieldBuilder requesterField,
            FieldInfo classHeadersField,
            AllowAnyStatusCodeAttribute classAllowAnyStatusCodeAttribute,
            SerializationMethodsAttribute classSerializationMethodsAttribute,
            PropertyGrouping properties,
            out MethodInfoGrouping methodInfoGrouping)
        {
            int i = 0;

            methodInfoGrouping = new MethodInfoGrouping();

            foreach (var methodInfo in InterfaceAndChildren(interfaceType, x => x.GetTypeInfo().GetMethods()))
            {
                // Exclude property getter / setters, etc
                if (methodInfo.IsSpecialName)
                {
                    continue;
                }

                var parameters        = methodInfo.GetParameters();
                var parameterGrouping = new ParameterGrouping(parameters, methodInfo.Name);

                var methodBuilder     = typeBuilder.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, methodInfo.ReturnType, parameters.Select(x => x.ParameterType).ToArray());
                var methodIlGenerator = methodBuilder.GetILGenerator();

                if (methodInfo == disposeMethod)
                {
                    this.AddDisposeMethod(methodIlGenerator, requesterField);
                }
                else
                {
                    var requestAttribute = methodInfo.GetCustomAttribute <RequestAttribute>();
                    if (requestAttribute == null)
                    {
                        throw new ImplementationCreationException(String.Format("Method {0} does not have a suitable [Get] / [Post] / etc attribute on it", methodInfo.Name));
                    }

                    var allowAnyStatusCodeAttribute = methodInfo.GetCustomAttribute <AllowAnyStatusCodeAttribute>();

                    var methodSerializationMethodsAttribute = methodInfo.GetCustomAttribute <SerializationMethodsAttribute>();
                    var serializationMethods = new ResolvedSerializationMethods(classSerializationMethodsAttribute, methodSerializationMethodsAttribute);

                    this.ValidatePathParams(requestAttribute.Path, parameterGrouping.PathParameters.Select(x => x.Attribute.Name ?? x.Parameter.Name).ToList(), properties.Path.Select(x => x.Attribute.Name).ToList(), methodInfo.Name);

                    var methodInfoFieldBuilder = typeBuilder.DefineField("methodInfo<>_" + i, typeof(MethodInfo), FieldAttributes.Private | FieldAttributes.Static);
                    methodInfoGrouping.Fields.Add(new MethodInfoFieldReference(methodInfo, methodInfoFieldBuilder));

                    this.AddRequestInfoCreation(methodIlGenerator, requesterField, requestAttribute, methodInfoFieldBuilder);
                    this.AddCancellationTokenIfNeeded(methodIlGenerator, parameterGrouping.CancellationToken);
                    this.AddClassHeadersIfNeeded(methodIlGenerator, classHeadersField);
                    this.AddPropertyHeaders(methodIlGenerator, properties.Headers);
                    this.AddPathProperties(methodIlGenerator, properties.Path);
                    this.AddMethodHeaders(methodIlGenerator, methodInfo);
                    this.AddAllowAnyStatusCodeIfNecessary(methodIlGenerator, allowAnyStatusCodeAttribute ?? classAllowAnyStatusCodeAttribute);
                    this.AddParameters(methodIlGenerator, parameterGrouping, methodInfo.Name, serializationMethods);
                    this.AddRequestMethodInvocation(methodIlGenerator, methodInfo);

                    // Finally, return
                    methodIlGenerator.Emit(OpCodes.Ret);

                    typeBuilder.DefineMethodOverride(methodBuilder, methodInfo);
                }

                i++;
            }
        }
        private void AddStaticCtor(TypeBuilder typeBuilder, HeaderAttribute[] classHeaders, FieldBuilder classHeadersField, MethodInfoGrouping methodInfoGrouping)
        {
            // static Name()
            // {
            //     classHeaders = new List<KeyValuePair<string>>(n);
            //     classHeaders.Add(new KeyValuePair<string, string>("name", "value"));
            //     ...
            //     methodInfoBackingField = new Lazy<MethodInfo>(methodInfoMethod);
            //     ...
            // }

            var staticCtorBuilder     = typeBuilder.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, new Type[0]);
            var staticCtorIlGenerator = staticCtorBuilder.GetILGenerator();

            if (classHeadersField != null)
            {
                // Load the list size onto the stack
                // Stack: [list size]
                staticCtorIlGenerator.Emit(OpCodes.Ldc_I4, classHeaders.Length);
                // Ctor the list
                // Stack: [list]
                staticCtorIlGenerator.Emit(OpCodes.Newobj, listOfKvpOfStringNCtor);
                // Load each class header into the list
                foreach (var classHeader in classHeaders)
                {
                    staticCtorIlGenerator.Emit(OpCodes.Dup);
                    staticCtorIlGenerator.Emit(OpCodes.Ldstr, classHeader.Name);
                    staticCtorIlGenerator.Emit(OpCodes.Ldstr, classHeader.Value); // This value can never be null - we assert that earlier
                    staticCtorIlGenerator.Emit(OpCodes.Newobj, kvpOfStringCtor);
                    staticCtorIlGenerator.Emit(OpCodes.Callvirt, listOfKvpOfStringAdd);
                }
                // Finally, store the list in its static field
                staticCtorIlGenerator.Emit(OpCodes.Stsfld, classHeadersField);
            }

            foreach (var field in methodInfoGrouping.Fields)
            {
                staticCtorIlGenerator.Emit(OpCodes.Ldtoken, field.MethodInfo);
                if (field.MethodInfo.DeclaringType.GetTypeInfo().IsGenericType)
                {
                    staticCtorIlGenerator.Emit(OpCodes.Ldtoken, field.MethodInfo.DeclaringType);
                    staticCtorIlGenerator.Emit(OpCodes.Call, getMethodFromHandleWithDeclaringTypeMethod);
                }
                else
                {
                    staticCtorIlGenerator.Emit(OpCodes.Call, getMethodFromHandleMethod);
                }
                staticCtorIlGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo));
                staticCtorIlGenerator.Emit(OpCodes.Stsfld, field.BackingField);
            }

            staticCtorIlGenerator.Emit(OpCodes.Ret);
        }