Пример #1
0
        FeignClientMethodInfo BuildMethod(TypeBuilder typeBuilder, Type serviceType, MethodInfo method, FeignClientAttribute feignClientAttribute, RequestMappingBaseAttribute requestMapping)
        {
            FeignClientMethodInfo feignClientMethodInfo = new FeignClientMethodInfo
            {
                MethodId       = GetMethodId(method),
                MethodMetadata = method
            };
            //创建方法
            MethodBuilder methodBuilder = CreateMethodBuilder(typeBuilder, method);
            ILGenerator   iLGenerator   = methodBuilder.GetILGenerator();

            if (requestMapping == null)
            {
                //如果找不到mapping,抛出 NotSupportedException 异常
                iLGenerator.Emit(OpCodes.Newobj, typeof(NotSupportedException).GetConstructor(Type.EmptyTypes));
                iLGenerator.Emit(OpCodes.Throw);
                return(new FeignClientMethodInfo
                {
                    MethodId = GetMethodId(method),
                    MethodMetadata = method
                });
            }
            string       uri       = requestMapping.Value ?? "";
            LocalBuilder local_Uri = iLGenerator.DeclareLocal(typeof(string)); // 定义uri

            iLGenerator.Emit(OpCodes.Ldstr, uri);
            iLGenerator.Emit(OpCodes.Stloc, local_Uri);
            List <EmitRequestContent> emitRequestContents = EmitParameter(typeBuilder, requestMapping, iLGenerator, method, local_Uri);

            EmitCallMethod(typeBuilder, methodBuilder, iLGenerator, serviceType, feignClientMethodInfo, requestMapping, local_Uri, emitRequestContents);
            methodBuilder.CopyCustomAttributes(method);
            return(feignClientMethodInfo);
        }
Пример #2
0
        protected override void EmitCallMethod(TypeBuilder typeBuilder, MethodBuilder methodBuilder, ILGenerator iLGenerator, Type serviceType, FeignClientMethodInfo feignClientMethodInfo, RequestMappingBaseAttribute requestMapping, LocalBuilder uri, List <EmitRequestContent> emitRequestContents)
        {
            var invokeMethod = GetInvokeMethod(serviceType, feignClientMethodInfo.MethodMetadata, requestMapping);

            if (emitRequestContents != null && emitRequestContents.Count > 0 && !SupportRequestContent(invokeMethod, requestMapping))
            {
                throw new NotSupportedException("不支持RequestBody或者RequestForm");
            }
            LocalBuilder feignClientRequest = DefineFeignClientRequest(typeBuilder, serviceType, iLGenerator, uri, requestMapping, emitRequestContents, feignClientMethodInfo);
            // fallback
            LocalBuilder fallbackDelegate = DefineFallbackDelegate(typeBuilder, methodBuilder, iLGenerator, serviceType, feignClientMethodInfo.MethodMetadata);

            iLGenerator.Emit(OpCodes.Ldarg_0);  //this
            iLGenerator.Emit(OpCodes.Ldloc, feignClientRequest);
            iLGenerator.Emit(OpCodes.Ldloc, fallbackDelegate);
            iLGenerator.Emit(OpCodes.Call, invokeMethod);
            iLGenerator.Emit(OpCodes.Ret);
        }
Пример #3
0
        ///// <summary>
        ///// 定义用于Send方法的FeignClientHttpRequest
        ///// </summary>
        ///// <param name="typeBuilder"></param>
        ///// <param name="serviceType"></param>
        ///// <param name="iLGenerator"></param>
        ///// <param name="uri"></param>
        ///// <param name="requestMapping"></param>
        ///// <param name="emitRequestContents"></param>
        ///// <param name="feignClientMethodInfo"></param>
        ///// <returns></returns>
        //protected LocalBuilder DefineFeignClientRequest_Old(TypeBuilder typeBuilder, Type serviceType, ILGenerator iLGenerator, LocalBuilder uri, RequestMappingBaseAttribute requestMapping, List<EmitRequestContent> emitRequestContents, FeignClientMethodInfo feignClientMethodInfo)
        //{
        //    LocalBuilder localBuilder = iLGenerator.DeclareLocal(typeof(FeignClientHttpRequest));
        //    // baseUrl
        //    PropertyInfo propertyInfo = typeof(FeignClientHttpProxy<>).MakeGenericType(serviceType).GetProperty("BaseUrl", BindingFlags.Instance | BindingFlags.NonPublic);
        //    iLGenerator.Emit(OpCodes.Ldarg_0); //this
        //    iLGenerator.Emit(OpCodes.Callvirt, propertyInfo.GetMethod);
        //    //mapping uri
        //    if (requestMapping.Value == null)
        //    {
        //        iLGenerator.Emit(OpCodes.Ldnull);
        //    }
        //    else
        //    {
        //        iLGenerator.Emit(OpCodes.Ldstr, requestMapping.Value);
        //    }
        //    //uri
        //    iLGenerator.Emit(OpCodes.Ldloc, uri);
        //    //httpMethod
        //    iLGenerator.Emit(OpCodes.Ldstr, requestMapping.GetMethod());

        //    //contentType
        //    string contentType = requestMapping.ContentType;
        //    if (string.IsNullOrWhiteSpace(contentType) && serviceType.IsDefined(typeof(RequestMappingAttribute)))
        //    {
        //        contentType = serviceType.GetCustomAttribute<RequestMappingAttribute>().ContentType;
        //    }
        //    if (contentType == null)
        //    {
        //        iLGenerator.Emit(OpCodes.Ldnull);
        //    }
        //    else
        //    {
        //        iLGenerator.Emit(OpCodes.Ldstr, contentType);
        //    }

        //    //accept
        //    string accept = requestMapping.Accept;
        //    if (string.IsNullOrWhiteSpace(contentType) && serviceType.IsDefined(typeof(RequestMappingAttribute)))
        //    {
        //        accept = serviceType.GetCustomAttribute<RequestMappingAttribute>().Accept;
        //    }
        //    if (accept == null)
        //    {
        //        iLGenerator.Emit(OpCodes.Ldnull);
        //    }
        //    else
        //    {
        //        iLGenerator.Emit(OpCodes.Ldstr, accept);
        //    }

        //    //headers
        //    List<IEmitValue<string>> headers = new List<IEmitValue<string>>();
        //    if (serviceType.IsDefined(typeof(HeadersAttribute), true))
        //    {
        //        var serviceHeaders = serviceType.GetCustomAttribute<HeadersAttribute>().Headers;
        //        if (serviceHeaders != null)
        //        {
        //            headers.AddRange(serviceHeaders.Select(s => new EmitConstantStringValue(s)));
        //        }
        //    }
        //    if (feignClientMethodInfo.MethodMetadata.IsDefined(typeof(HeadersAttribute), true))
        //    {
        //        var methodHeaders = feignClientMethodInfo.MethodMetadata.GetCustomAttribute<HeadersAttribute>().Headers;
        //        if (methodHeaders != null)
        //        {
        //            headers.AddRange(methodHeaders.Select(s => new EmitConstantStringValue(s)));
        //        }
        //    }
        //    if (headers.Count == 0)
        //    {
        //        iLGenerator.Emit(OpCodes.Ldnull);
        //    }
        //    else
        //    {
        //        iLGenerator.EmitStringArray(headers);
        //    }

        //    //requestContent
        //    if (emitRequestContents != null && emitRequestContents.Count > 0)
        //    {
        //        if (emitRequestContents.Count == 1)
        //        {
        //            if (typeof(IHttpRequestFile).IsAssignableFrom(emitRequestContents[0].Parameter.ParameterType))
        //            {
        //                EmitFeignClientMultipartRequestContent(iLGenerator, emitRequestContents);
        //            }
        //            else
        //            {
        //                EmitFeignClientRequestContent(iLGenerator, emitRequestContents[0], null);
        //            }
        //        }
        //        else if (emitRequestContents.Any(s => !s.SupportMultipart))
        //        {
        //            throw new NotSupportedException("最多只支持一个RequestContent \r\n " + feignClientMethodInfo.ToString());
        //        }
        //        else
        //        {
        //            EmitFeignClientMultipartRequestContent(iLGenerator, emitRequestContents);
        //        }
        //    }
        //    else
        //    {
        //        iLGenerator.Emit(OpCodes.Ldnull);
        //    }
        //    #region new

        //    //feignClientMethodInfo
        //    //feignClientMethodInfo=null
        //    LocalBuilder feignClientMethodInfoLocalBuilder = iLGenerator.DeclareLocal(typeof(FeignClientMethodInfo));
        //    iLGenerator.Emit(OpCodes.Newobj, typeof(FeignClientMethodInfo).GetEmptyConstructor());
        //    iLGenerator.Emit(OpCodes.Stloc, feignClientMethodInfoLocalBuilder);
        //    iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
        //    iLGenerator.Emit(OpCodes.Ldstr, feignClientMethodInfo.MethodId);
        //    iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("MethodId").SetMethod);

        //    #region ResultType
        //    //feignClientMethodInfo.ResultType=typeof(xx);
        //    ResultTypeAttribute resultTypeAttribute = feignClientMethodInfo.MethodMetadata.GetCustomAttribute<ResultTypeAttribute>();
        //    Type returnType = GetReturnType(feignClientMethodInfo.MethodMetadata);
        //    if (returnType != null && resultTypeAttribute != null)
        //    {
        //        Type resultType = resultTypeAttribute.ConvertType(returnType);
        //        if (resultType != null)
        //        {
        //            iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
        //            iLGenerator.EmitType(resultType);
        //            iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("ResultType").SetMethod);
        //        }
        //    }
        //    #endregion


        //    Label newFeingClientRequestLabel = iLGenerator.DefineLabel();

        //    #region if (base.FeignOptions.IncludeMethodMetadata) set the call method
        //    //这里获取方法元数据
        //    PropertyInfo feignOptionsProperty = typeBuilder.BaseType.GetProperty("FeignOptions", BindingFlags.Instance | BindingFlags.NonPublic);
        //    PropertyInfo includeMethodMetadataProperty = feignOptionsProperty.PropertyType.GetProperty("IncludeMethodMetadata");
        //    iLGenerator.Emit(OpCodes.Ldarg_0);
        //    iLGenerator.Emit(OpCodes.Call, feignOptionsProperty.GetMethod);
        //    iLGenerator.Emit(OpCodes.Callvirt, includeMethodMetadataProperty.GetMethod);
        //    iLGenerator.Emit(OpCodes.Ldc_I4, 1);
        //    iLGenerator.Emit(OpCodes.Ceq);
        //    iLGenerator.Emit(OpCodes.Brfalse_S, newFeingClientRequestLabel);
        //    iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
        //    iLGenerator.EmitMethodInfo(feignClientMethodInfo.MethodMetadata);
        //    iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("MethodMetadata").SetMethod);
        //    #endregion
        //    //处理下 if GOTO
        //    iLGenerator.MarkLabel(newFeingClientRequestLabel);

        //    iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
        //    iLGenerator.Emit(OpCodes.Newobj, typeof(FeignClientHttpRequest).GetFirstConstructor());
        //    #region HttpCompletionOption
        //    //CompletionOption=requestMapping.CompletionOption.Value;
        //    iLGenerator.Emit(OpCodes.Dup);
        //    iLGenerator.EmitEnumValue(requestMapping.CompletionOption);
        //    iLGenerator.Emit(OpCodes.Callvirt, typeof(FeignClientHttpRequest).GetProperty("CompletionOption").SetMethod);
        //    #endregion
        //    iLGenerator.Emit(OpCodes.Stloc, localBuilder);


        //    //#region request headers
        //    //// request headers
        //    //List<Tuple<int, ParameterInfo, RequestHeaderBaseAttribute>> headerBaseAttributes = new List<Tuple<int, ParameterInfo, RequestHeaderBaseAttribute>>();
        //    //int parameterIndex = -1;
        //    //foreach (var item in feignClientMethodInfo.MethodMetadata.GetParameters())
        //    //{
        //    //    parameterIndex++;
        //    //    if (!item.IsDefined(typeof(RequestHeaderBaseAttribute)))
        //    //    {
        //    //        continue;
        //    //    }
        //    //    headerBaseAttributes.Add(Tuple.Create(parameterIndex, item, item.GetCustomAttribute<RequestHeaderBaseAttribute>()));
        //    //}
        //    //if (headerBaseAttributes.Count > 0)
        //    //{
        //    //    //feignClientHttpRequest.RequestHeaderHandlers = new List<IRequestHeaderHandler>();
        //    //    iLGenerator.Emit(OpCodes.Ldloc, localBuilder);
        //    //    iLGenerator.Emit(OpCodes.Newobj, typeof(List<IRequestHeaderHandler>).GetEmptyConstructor());
        //    //    iLGenerator.Emit(OpCodes.Callvirt, typeof(FeignClientHttpRequest).GetProperty("RequestHeaderHandlers").SetMethod);

        //    //    MethodInfo listAddItemMethodInfo = typeof(List<IRequestHeaderHandler>).GetMethod("Add");
        //    //    foreach (var headerBaseAttribute in headerBaseAttributes)
        //    //    {
        //    //        //string text2 = "xxx";
        //    //        //feignClientHttpRequest.RequestHeaderHandlers.Add(new RequestHeaderHandler("xxx", text2));
        //    //        var valueBuilder = iLGenerator.DeclareLocal(typeof(string));
        //    //        if (headerBaseAttribute.Item2.ParameterType == typeof(string))
        //    //        {
        //    //            iLGenerator.Emit(OpCodes.Ldarg_S, headerBaseAttribute.Item1 + 1);
        //    //        }
        //    //        else
        //    //        {
        //    //            iLGenerator.Emit(OpCodes.Ldstr, "test");
        //    //        }
        //    //        iLGenerator.Emit(OpCodes.Stloc, valueBuilder);
        //    //        var handlerLocalBuilder = headerBaseAttribute.Item3.EmitNewRequestHeaderHandler(iLGenerator, valueBuilder);
        //    //        if (handlerLocalBuilder!=null)
        //    //        {
        //    //            iLGenerator.Emit(OpCodes.Ldloc, localBuilder);
        //    //            iLGenerator.Emit(OpCodes.Callvirt, typeof(FeignClientHttpRequest).GetProperty("RequestHeaderHandlers").GetMethod);
        //    //            iLGenerator.Emit(OpCodes.Callvirt, listAddItemMethodInfo);
        //    //        }
        //    //    }
        //    //}
        //    //#endregion

        //    return localBuilder;
        //    #endregion
        //}
        #endregion


        /// <summary>
        /// 定义用于Send方法的FeignClientHttpRequest
        /// </summary>
        /// <param name="typeBuilder"></param>
        /// <param name="serviceType"></param>
        /// <param name="iLGenerator"></param>
        /// <param name="uri"></param>
        /// <param name="requestMapping"></param>
        /// <param name="emitRequestContents"></param>
        /// <param name="feignClientMethodInfo"></param>
        /// <returns></returns>
        protected LocalBuilder DefineFeignClientRequest(TypeBuilder typeBuilder, Type serviceType, ILGenerator iLGenerator, LocalBuilder uri, RequestMappingBaseAttribute requestMapping, List <EmitRequestContent> emitRequestContents, FeignClientMethodInfo feignClientMethodInfo)
        {
            LocalBuilder localBuilder = iLGenerator.DeclareLocal(typeof(FeignClientHttpRequest));

            #region localBuilder = new FeignClientHttpRequest(string baseUrl, string mappingUri, string uri, string httpMethod, string contentType)

            // baseUrl
            iLGenerator.Emit(OpCodes.Ldarg_0); //this
            iLGenerator.Emit(OpCodes.Callvirt, typeof(FeignClientHttpProxy <>).MakeGenericType(serviceType).GetProperty("BaseUrl", BindingFlags.Instance | BindingFlags.NonPublic).GetMethod);

            //mapping uri
            if (requestMapping.Value == null)
            {
                iLGenerator.Emit(OpCodes.Ldnull);
            }
            else
            {
                iLGenerator.Emit(OpCodes.Ldstr, requestMapping.Value);
            }
            //uri
            iLGenerator.Emit(OpCodes.Ldloc, uri);
            //httpMethod
            iLGenerator.Emit(OpCodes.Ldstr, requestMapping.GetMethod());

            //contentType
            string contentType = requestMapping.ContentType;
            if (string.IsNullOrWhiteSpace(contentType) && serviceType.IsDefined(typeof(RequestMappingAttribute)))
            {
                contentType = serviceType.GetCustomAttribute <RequestMappingAttribute>().ContentType;
            }
            if (contentType == null)
            {
                iLGenerator.Emit(OpCodes.Ldnull);
            }
            else
            {
                iLGenerator.Emit(OpCodes.Ldstr, contentType);
            }

            //new FeignClientHttpRequest(baseUrl, mappingUri, uri, httpMethod, contentType)
            iLGenerator.Emit(OpCodes.Newobj, typeof(FeignClientHttpRequest).GetFirstConstructor());
            #region HttpCompletionOption
            //CompletionOption=requestMapping.CompletionOption.Value;
            iLGenerator.Emit(OpCodes.Dup);
            iLGenerator.EmitEnumValue(requestMapping.CompletionOption);
            iLGenerator.Emit(OpCodes.Callvirt, typeof(FeignClientHttpRequest).GetProperty("CompletionOption").SetMethod);
            #endregion
            iLGenerator.Emit(OpCodes.Stloc, localBuilder);

            #endregion

            #region FeignClientHttpRequest.Method
            //feignClientMethodInfo
            //feignClientMethodInfo=null
            LocalBuilder feignClientMethodInfoLocalBuilder = iLGenerator.DeclareLocal(typeof(FeignClientMethodInfo));
            iLGenerator.Emit(OpCodes.Newobj, typeof(FeignClientMethodInfo).GetEmptyConstructor());
            iLGenerator.Emit(OpCodes.Stloc, feignClientMethodInfoLocalBuilder);
            iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
            iLGenerator.Emit(OpCodes.Ldstr, feignClientMethodInfo.MethodId);
            iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("MethodId").SetMethod);
            #region ResultType
            //feignClientMethodInfo.ResultType=typeof(xx);
            ResultTypeAttribute resultTypeAttribute = feignClientMethodInfo.MethodMetadata.GetCustomAttribute <ResultTypeAttribute>();
            Type returnType = GetReturnType(feignClientMethodInfo.MethodMetadata);
            if (returnType != null && resultTypeAttribute != null)
            {
                Type resultType = resultTypeAttribute.ConvertType(returnType);
                if (resultType != null)
                {
                    iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
                    iLGenerator.EmitType(resultType);
                    iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("ResultType").SetMethod);
                }
            }
            #endregion

            Label newFeingClientRequestLabel = iLGenerator.DefineLabel();

            #region if (base.FeignOptions.IncludeMethodMetadata) set the call method
            //这里获取方法元数据
            PropertyInfo feignOptionsProperty          = typeBuilder.BaseType.GetProperty("FeignOptions", BindingFlags.Instance | BindingFlags.NonPublic);
            PropertyInfo includeMethodMetadataProperty = feignOptionsProperty.PropertyType.GetProperty("IncludeMethodMetadata");
            iLGenerator.Emit(OpCodes.Ldarg_0);
            iLGenerator.Emit(OpCodes.Call, feignOptionsProperty.GetMethod);
            iLGenerator.Emit(OpCodes.Callvirt, includeMethodMetadataProperty.GetMethod);
            iLGenerator.Emit(OpCodes.Ldc_I4, 1);
            iLGenerator.Emit(OpCodes.Ceq);
            iLGenerator.Emit(OpCodes.Brfalse_S, newFeingClientRequestLabel);
            iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
            iLGenerator.EmitMethodInfo(feignClientMethodInfo.MethodMetadata);
            iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("MethodMetadata").SetMethod);
            #endregion
            //处理下 if GOTO
            iLGenerator.MarkLabel(newFeingClientRequestLabel);
            iLGenerator.Emit(OpCodes.Ldloc, localBuilder);
            iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
            iLGenerator.Emit(OpCodes.Call, typeof(FeignClientHttpRequest).GetProperty("Method").SetMethod);
            #endregion

            #region FeignClientHttpRequest.Accept
            //accept
            string accept = requestMapping.Accept;
            if (string.IsNullOrWhiteSpace(accept) && serviceType.IsDefined(typeof(RequestMappingAttribute)))
            {
                accept = serviceType.GetCustomAttribute <RequestMappingAttribute>().Accept;
            }
            if (accept != null)
            {
                iLGenerator.Emit(OpCodes.Ldloc, localBuilder);
                iLGenerator.Emit(OpCodes.Ldstr, accept);
                iLGenerator.Emit(OpCodes.Call, typeof(FeignClientHttpRequest).GetProperty("Accept").SetMethod);
            }

            #endregion

            #region FeignClientHttpRequest.Headers
            //headers
            List <IEmitValue <string> > headers = new List <IEmitValue <string> >();
            if (serviceType.IsDefined(typeof(HeadersAttribute), true))
            {
                var serviceHeaders = serviceType.GetCustomAttribute <HeadersAttribute>().Headers;
                if (serviceHeaders != null)
                {
                    headers.AddRange(serviceHeaders.Select(s => new EmitConstantStringValue(s)));
                }
            }
            if (feignClientMethodInfo.MethodMetadata.IsDefined(typeof(HeadersAttribute), true))
            {
                var methodHeaders = feignClientMethodInfo.MethodMetadata.GetCustomAttribute <HeadersAttribute>().Headers;
                if (methodHeaders != null)
                {
                    headers.AddRange(methodHeaders.Select(s => new EmitConstantStringValue(s)));
                }
            }
            if (headers.Count >= 0)
            {
                iLGenerator.Emit(OpCodes.Ldloc, localBuilder);
                iLGenerator.EmitStringArray(headers);
                iLGenerator.Emit(OpCodes.Call, typeof(FeignClientHttpRequest).GetProperty("Headers").SetMethod);
            }
            #endregion

            #region FeignClientHttpRequest.RequestContent
            //requestContent
            if (emitRequestContents != null && emitRequestContents.Count > 0)
            {
                iLGenerator.Emit(OpCodes.Ldloc, localBuilder);
                if (emitRequestContents.Count == 1)
                {
                    if (typeof(IHttpRequestFile).IsAssignableFrom(emitRequestContents[0].Parameter.ParameterType))
                    {
                        EmitFeignClientMultipartRequestContent(iLGenerator, emitRequestContents);
                    }
                    else
                    {
                        EmitFeignClientRequestContent(iLGenerator, emitRequestContents[0], null);
                    }
                }
                else if (emitRequestContents.Any(s => !s.SupportMultipart))
                {
                    throw new NotSupportedException("最多只支持一个RequestContent \r\n " + feignClientMethodInfo.ToString());
                }
                else
                {
                    EmitFeignClientMultipartRequestContent(iLGenerator, emitRequestContents);
                }
                iLGenerator.Emit(OpCodes.Call, typeof(FeignClientHttpRequest).GetProperty("RequestContent").SetMethod);
            }
            #endregion

            #region FeignClientHttpRequest.RequestHeaderHandlers
            // request headers
            List <Tuple <int, ParameterInfo, RequestHeaderBaseAttribute> > headerBaseAttributes = new List <Tuple <int, ParameterInfo, RequestHeaderBaseAttribute> >();
            int parameterIndex = -1;
            foreach (var item in feignClientMethodInfo.MethodMetadata.GetParameters())
            {
                parameterIndex++;
                if (!item.IsDefined(typeof(RequestHeaderBaseAttribute)))
                {
                    continue;
                }
                headerBaseAttributes.Add(Tuple.Create(parameterIndex, item, item.GetCustomAttribute <RequestHeaderBaseAttribute>()));
            }
            if (headerBaseAttributes.Count > 0)
            {
                //feignClientHttpRequest.RequestHeaderHandlers = new List<IRequestHeaderHandler>();
                iLGenerator.Emit(OpCodes.Ldloc, localBuilder);
                iLGenerator.Emit(OpCodes.Newobj, typeof(List <IRequestHeaderHandler>).GetEmptyConstructor());
                iLGenerator.Emit(OpCodes.Callvirt, typeof(FeignClientHttpRequest).GetProperty("RequestHeaderHandlers").SetMethod);

                MethodInfo listAddItemMethodInfo = typeof(List <IRequestHeaderHandler>).GetMethod("Add");
                foreach (var headerBaseAttribute in headerBaseAttributes)
                {
                    //string text2 = "xxx";
                    //feignClientHttpRequest.RequestHeaderHandlers.Add(new RequestHeaderHandler("xxx", text2));
                    var valueBuilder = iLGenerator.DeclareLocal(typeof(string));
                    iLGenerator.Emit(OpCodes.Ldarg_S, headerBaseAttribute.Item1 + 1);
                    if (headerBaseAttribute.Item2.ParameterType != typeof(string))
                    {
                        iLGenerator.Emit(OpCodes.Call, GetConvertToStringValueMethod(typeBuilder, headerBaseAttribute.Item2.ParameterType));
                    }
                    iLGenerator.Emit(OpCodes.Stloc, valueBuilder);
                    var handlerLocalBuilder = headerBaseAttribute.Item3.EmitNewRequestHeaderHandler(iLGenerator, valueBuilder);
                    if (handlerLocalBuilder != null)
                    {
                        iLGenerator.Emit(OpCodes.Ldloc, localBuilder);
                        iLGenerator.Emit(OpCodes.Callvirt, typeof(FeignClientHttpRequest).GetProperty("RequestHeaderHandlers").GetMethod);
                        iLGenerator.Emit(OpCodes.Ldloc, handlerLocalBuilder);
                        iLGenerator.Emit(OpCodes.Callvirt, listAddItemMethodInfo);
                    }
                }
            }
            #endregion

            return(localBuilder);
        }
Пример #4
0
        /// <summary>
        /// 定义用于Send方法的FeignClientHttpRequest
        /// </summary>
        /// <param name="typeBuilder"></param>
        /// <param name="serviceType"></param>
        /// <param name="iLGenerator"></param>
        /// <param name="uri"></param>
        /// <param name="requestMapping"></param>
        /// <param name="emitRequestContents"></param>
        /// <param name="feignClientMethodInfo"></param>
        /// <returns></returns>
        protected LocalBuilder DefineFeignClientRequest(TypeBuilder typeBuilder, Type serviceType, ILGenerator iLGenerator, LocalBuilder uri, RequestMappingBaseAttribute requestMapping, List <EmitRequestContent> emitRequestContents, FeignClientMethodInfo feignClientMethodInfo)
        {
            LocalBuilder localBuilder = iLGenerator.DeclareLocal(typeof(FeignClientHttpRequest));

            // baseUrl
            EmitBaseUrl(iLGenerator, serviceType);
            //mapping uri
            if (requestMapping.Value == null)
            {
                iLGenerator.Emit(OpCodes.Ldnull);
            }
            else
            {
                iLGenerator.Emit(OpCodes.Ldstr, requestMapping.Value);
            }
            //uri
            iLGenerator.Emit(OpCodes.Ldloc, uri);
            //httpMethod
            iLGenerator.Emit(OpCodes.Ldstr, requestMapping.GetMethod());

            //contentType
            string contentType = requestMapping.ContentType;

            if (string.IsNullOrWhiteSpace(contentType) && serviceType.IsDefined(typeof(RequestMappingAttribute)))
            {
                contentType = serviceType.GetCustomAttribute <RequestMappingAttribute>().ContentType;
            }
            if (contentType == null)
            {
                iLGenerator.Emit(OpCodes.Ldnull);
            }
            else
            {
                iLGenerator.Emit(OpCodes.Ldstr, contentType);
            }

            //accept
            string accept = requestMapping.Accept;

            if (string.IsNullOrWhiteSpace(contentType) && serviceType.IsDefined(typeof(RequestMappingAttribute)))
            {
                accept = serviceType.GetCustomAttribute <RequestMappingAttribute>().Accept;
            }
            if (accept == null)
            {
                iLGenerator.Emit(OpCodes.Ldnull);
            }
            else
            {
                iLGenerator.Emit(OpCodes.Ldstr, accept);
            }

            //headers
            List <string> headers = new List <string>();

            if (serviceType.IsDefined(typeof(HeadersAttribute), true))
            {
                var serviceHeaders = serviceType.GetCustomAttribute <HeadersAttribute>().Headers;
                if (serviceHeaders != null)
                {
                    headers.AddRange(serviceHeaders);
                }
            }
            if (feignClientMethodInfo.MethodMetadata.IsDefined(typeof(HeadersAttribute), true))
            {
                var methodHeaders = feignClientMethodInfo.MethodMetadata.GetCustomAttribute <HeadersAttribute>().Headers;
                if (methodHeaders != null)
                {
                    headers.AddRange(methodHeaders);
                }
            }
            if (headers.Count == 0)
            {
                iLGenerator.Emit(OpCodes.Ldnull);
            }
            else
            {
                iLGenerator.EmitStringArray(headers);
            }

            //requestContent
            if (emitRequestContents != null && emitRequestContents.Count > 0)
            {
                if (emitRequestContents.Count == 1)
                {
                    if (typeof(IHttpRequestFile).IsAssignableFrom(emitRequestContents[0].Parameter.ParameterType))
                    {
                        EmitFeignClientMultipartRequestContent(iLGenerator, emitRequestContents);
                    }
                    else
                    {
                        EmitFeignClientRequestContent(iLGenerator, emitRequestContents[0], null);
                    }
                }
                else if (emitRequestContents.Any(s => !s.SupportMultipart))
                {
                    throw new NotSupportedException("最多只支持一个RequestContent \r\n " + feignClientMethodInfo.ToString());
                }
                else
                {
                    EmitFeignClientMultipartRequestContent(iLGenerator, emitRequestContents);
                }
            }
            else
            {
                iLGenerator.Emit(OpCodes.Ldnull);
            }
            #region new

            //feignClientMethodInfo
            //feignClientMethodInfo=null
            LocalBuilder feignClientMethodInfoLocalBuilder = iLGenerator.DeclareLocal(typeof(FeignClientMethodInfo));
            iLGenerator.Emit(OpCodes.Newobj, typeof(FeignClientMethodInfo).GetConstructors()[0]);
            iLGenerator.Emit(OpCodes.Stloc, feignClientMethodInfoLocalBuilder);
            iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
            iLGenerator.Emit(OpCodes.Ldstr, feignClientMethodInfo.MethodId);
            iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("MethodId").SetMethod);

            #region ResultType
            //feignClientMethodInfo.ResultType=typeof(xx);
            ResultTypeAttribute resultTypeAttribute = feignClientMethodInfo.MethodMetadata.GetCustomAttribute <ResultTypeAttribute>();
            Type returnType = GetReturnType(feignClientMethodInfo.MethodMetadata);
            if (returnType != null && resultTypeAttribute != null)
            {
                Type resultType = resultTypeAttribute.ConvertType(returnType);
                if (resultType != null)
                {
                    iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
                    iLGenerator.EmitType(resultType);
                    iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("ResultType").SetMethod);
                }
            }
            #endregion


            Label newFeingClientRequestLabel = iLGenerator.DefineLabel();

            #region if (base.FeignOptions.IncludeMethodMetadata) set the call method
            //这里获取方法元数据
            PropertyInfo feignOptionsProperty          = typeBuilder.BaseType.GetProperty("FeignOptions", BindingFlags.Instance | BindingFlags.NonPublic);
            PropertyInfo includeMethodMetadataProperty = feignOptionsProperty.PropertyType.GetProperty("IncludeMethodMetadata");
            iLGenerator.Emit(OpCodes.Ldarg_0);
            iLGenerator.Emit(OpCodes.Call, feignOptionsProperty.GetMethod);
            iLGenerator.Emit(OpCodes.Callvirt, includeMethodMetadataProperty.GetMethod);
            iLGenerator.Emit(OpCodes.Ldc_I4, 1);
            iLGenerator.Emit(OpCodes.Ceq);
            iLGenerator.Emit(OpCodes.Brfalse_S, newFeingClientRequestLabel);
            iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
            iLGenerator.EmitMethodInfo(feignClientMethodInfo.MethodMetadata);
            iLGenerator.Emit(OpCodes.Call, typeof(FeignClientMethodInfo).GetProperty("MethodMetadata").SetMethod);
            #endregion
            //处理下 if GOTO
            iLGenerator.MarkLabel(newFeingClientRequestLabel);

            iLGenerator.Emit(OpCodes.Ldloc, feignClientMethodInfoLocalBuilder);
            iLGenerator.Emit(OpCodes.Newobj, typeof(FeignClientHttpRequest).GetConstructors()[0]);
            #region HttpCompletionOption
            //CompletionOption=requestMapping.CompletionOption.Value;
            iLGenerator.Emit(OpCodes.Dup);
            iLGenerator.EmitEnumValue(requestMapping.CompletionOption);
            iLGenerator.Emit(OpCodes.Callvirt, typeof(FeignClientHttpRequest).GetProperty("CompletionOption").SetMethod);
            #endregion
            iLGenerator.Emit(OpCodes.Stloc, localBuilder);

            return(localBuilder);

            #endregion
        }