/// <summary>
        /// 生成Grpc方法(CodeFirst方式,用于生成BaseService)
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="srv"></param>
        /// <param name="methodName"></param>
        /// <param name="package"></param>
        /// <param name="srvName"></param>
        /// <param name="mType"></param>
        /// <returns></returns>
        public static Method <TRequest, TResponse> BuildMethod <TRequest, TResponse>(this IGrpcService srv,
                                                                                     string methodName, string package = null, string srvName = null, MethodType mType = MethodType.Unary)
        {
            var serviceName = srvName ??
                              GrpcExtensionsOptions.Instance.GlobalService ??
                              srv.GetType().Name;
            var pkg = package ?? GrpcExtensionsOptions.Instance.GlobalPackage;

            if (!string.IsNullOrWhiteSpace(pkg))
            {
                serviceName = $"{pkg}.{serviceName}";
            }
            #region 为生成proto收集信息
            if (!(srv is IGrpcBaseService) || GrpcExtensionsOptions.Instance.GenBaseServiceProtoEnable)
            {
                ProtoInfo.Methods.Add(new ProtoMethodInfo
                {
                    ServiceName  = serviceName,
                    MethodName   = methodName,
                    RequestName  = typeof(TRequest).Name,
                    ResponseName = typeof(TResponse).Name,
                    MethodType   = mType
                });
                ProtoGenerator.AddProto <TRequest>(typeof(TRequest).Name);
                ProtoGenerator.AddProto <TResponse>(typeof(TResponse).Name);
            }
            #endregion
            var request  = Marshallers.Create <TRequest>((arg) => ProtobufExtensions.Serialize <TRequest>(arg), data => ProtobufExtensions.Deserialize <TRequest>(data));
            var response = Marshallers.Create <TResponse>((arg) => ProtobufExtensions.Serialize <TResponse>(arg), data => ProtobufExtensions.Deserialize <TResponse>(data));
            return(new Method <TRequest, TResponse>(mType, serviceName, methodName, request, response));
        }
        /// <summary>
        /// 生成Grpc方法(CodeFirst方式,用于生成BaseService)
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="srv"></param>
        /// <param name="methodName"></param>
        /// <param name="package"></param>
        /// <param name="srvName"></param>
        /// <param name="mType"></param>
        /// <returns></returns>
        public static Method <TRequest, TResponse> BuildMethod <TRequest, TResponse>(this IGrpcService srv,
                                                                                     string methodName, string package = null, string srvName = null, MethodType mType = MethodType.Unary)
        {
            var serviceName = srvName ??
                              GrpcExtensionsOptions.Instance.GlobalService ??
                              srv.GetType().Name;
            var pkg = package ?? GrpcExtensionsOptions.Instance.GlobalPackage;

            if (!string.IsNullOrWhiteSpace(pkg))
            {
                serviceName = $"{pkg}.{serviceName}";
            }
            var request  = Marshallers.Create <TRequest>((arg) => ProtobufExtensions.Serialize <TRequest>(arg), data => ProtobufExtensions.Deserialize <TRequest>(data));
            var response = Marshallers.Create <TResponse>((arg) => ProtobufExtensions.Serialize <TResponse>(arg), data => ProtobufExtensions.Deserialize <TResponse>(data));

            return(new Method <TRequest, TResponse>(mType, serviceName, methodName, request, response));
        }
        /// <summary>
        /// 生成Grpc方法(CodeFirst方式)
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="srv"></param>
        /// <param name="methodName"></param>
        /// <param name="package"></param>
        /// <param name="srvName"></param>
        /// <param name="mType"></param>
        /// <returns></returns>
        public static Method <TRequest, TResponse> BuildMethod <TRequest, TResponse>(this IGrpcService srv,
                                                                                     string methodName, string package = null, string srvName = null, MethodType mType = MethodType.Unary)
        {
            var serviceName = srvName ??
                              GrpcExtensionsOptions.Instance.GlobalService ??
                              (srv.GetType().FullName.StartsWith("Castle.Proxies.") ? srv.GetType().Name.Substring(0, srv.GetType().Name.Length - 5) : srv.GetType().Name);
            var pkg = package ?? GrpcExtensionsOptions.Instance.GlobalPackage;

            if (!string.IsNullOrWhiteSpace(pkg))
            {
                serviceName = $"{pkg}.{serviceName}";
            }
            #region 为生成proto收集信息
            if (!(srv is IGrpcBaseService) || GrpcExtensionsOptions.Instance.GenBaseServiceProtoEnable)
            {
                var protoMethodInfo = new ProtoMethodInfo
                {
                    ServiceName  = serviceName,
                    MethodName   = methodName,
                    RequestName  = typeof(TRequest).Name,
                    ResponseName = typeof(TResponse).Name,
                    MethodType   = mType
                };
                if (typeof(TRequest).IsGenericType)
                {
                    protoMethodInfo.RequestName = $"{protoMethodInfo.RequestName.Substring(0, protoMethodInfo.RequestName.IndexOf('`'))}_{typeof(TRequest).GetGenericArguments()[0].Name}";
                }
                if (typeof(TResponse).IsGenericType)
                {
                    protoMethodInfo.ResponseName = $"{protoMethodInfo.ResponseName.Substring(0, protoMethodInfo.ResponseName.IndexOf('`'))}_{typeof(TResponse).GetGenericArguments()[0].Name}";
                }

                ProtoInfo.Methods.Add(protoMethodInfo);
                ProtoGenerator.AddProto <TRequest>(protoMethodInfo.RequestName);
                ProtoGenerator.AddProto <TResponse>(protoMethodInfo.ResponseName);
            }
            #endregion
            var request  = Marshallers.Create <TRequest>((arg) => ProtobufExtensions.Serialize <TRequest>(arg), data => ProtobufExtensions.Deserialize <TRequest>(data));
            var response = Marshallers.Create <TResponse>((arg) => ProtobufExtensions.Serialize <TResponse>(arg), data => ProtobufExtensions.Deserialize <TResponse>(data));
            return(new Method <TRequest, TResponse>(mType, serviceName, methodName, request, response));
        }
        /// <summary>
        /// 自动注册服务方法
        /// </summary>
        /// <param name="srv"></param>
        /// <param name="builder"></param>
        /// <param name="package"></param>
        /// <param name="serviceName"></param>
        public static void AutoRegisterMethod(IGrpcService srv, ServerServiceDefinition.Builder builder, string package = null, string serviceName = null)
        {
            var methods = srv.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

            foreach (var method in methods)
            {
                if (!method.ReturnType.Name.StartsWith("Task"))
                {
                    continue;
                }
                var parameters = method.GetParameters();
                if (parameters[parameters.Length - 1].ParameterType != typeof(ServerCallContext) ||
                    method.CustomAttributes.Any(x => x.AttributeType == typeof(NotGrpcMethodAttribute)))
                {
                    continue;
                }

                Type inputType  = parameters[0].ParameterType;
                Type inputType2 = parameters[1].ParameterType;
                Type outputType = method.ReturnType.IsGenericType ? method.ReturnType.GenericTypeArguments[0] : method.ReturnType;

                var addMethod        = unaryAddMethod;
                var serverMethodType = typeof(UnaryServerMethod <,>);
                var methodType       = MethodType.Unary;
                var reallyInputType  = inputType;
                var reallyOutputType = outputType;

                //非一元方法
                if ((inputType.IsGenericType || inputType2.IsGenericType))
                {
                    if (inputType.Name == "IAsyncStreamReader`1")
                    {
                        reallyInputType = inputType.GenericTypeArguments[0];
                        if (inputType2.Name == "IServerStreamWriter`1")//双向流
                        {
                            addMethod        = duplexStreamingAddMethod;
                            methodType       = MethodType.DuplexStreaming;
                            serverMethodType = typeof(DuplexStreamingServerMethod <,>);
                            reallyOutputType = inputType2.GenericTypeArguments[0];
                        }
                        else//客户端流
                        {
                            addMethod        = clientStreamingAddMethod;
                            methodType       = MethodType.ClientStreaming;
                            serverMethodType = typeof(ClientStreamingServerMethod <,>);
                        }
                    }
                    else if (inputType2.Name == "IServerStreamWriter`1")//服务端流
                    {
                        addMethod        = serverStreamingAddMethod;
                        methodType       = MethodType.ServerStreaming;
                        serverMethodType = typeof(ServerStreamingServerMethod <,>);
                        reallyOutputType = inputType2.GenericTypeArguments[0];
                    }
                }
                var buildMethodResult = buildMethod.MakeGenericMethod(reallyInputType, reallyOutputType)
                                        .Invoke(null, new object[] { srv, method.Name, package, serviceName, methodType });
                Delegate serverMethodDelegate = method.CreateDelegate(serverMethodType
                                                                      .MakeGenericType(reallyInputType, reallyOutputType), method.IsStatic ? null : srv);
                addMethod.MakeGenericMethod(reallyInputType, reallyOutputType).Invoke(builder, new[] { buildMethodResult, serverMethodDelegate });
            }
        }