Esempio n. 1
0
        /// <summary>
        /// Register GrpcClient
        /// </summary>
        /// <param name="hostBuilder">The host builder context</param>
        /// <param name="builderAction">The client options builder action</param>
        /// <param name="configurationKeyName">The client optios key in appsetting.json</param>
        /// <returns></returns>
        public static IHostBuilder UseGrpcClient(this IHostBuilder hostBuilder, Action <HostBuilderContext, IServiceCollection, ClientBuilder> builderAction = null, string configurationKeyName = "GrpcClient")
        {
            hostBuilder.ConfigureServices((context, services) =>
            {
                var builder           = context.Configuration.GetSection(configurationKeyName).Get <ClientBuilder>() ?? new ClientBuilder();
                builder.Configuration = context.Configuration;
                builder.Services      = services;
                builderAction?.Invoke(context, services, builder);
                var client = builder.Build();

                var codeBuilder = new CodeBuilder("CodeGenerate");
                foreach (var proxyer in client.Proxyers)
                {
                    codeBuilder.CreateClass(new ServicerProxyGenerator(proxyer.Options.PackageName, proxyer.ServicerTypes.ToList()).Generate().ToArray());
                    codeBuilder.AddAssemblyRefence(proxyer.Options.Assemblies.ToArray());
                }
                codeBuilder.AddAssemblyRefence(Assembly.GetExecutingAssembly())
                .AddAssemblyRefence(typeof(ServerServiceDefinition).Assembly)
                .AddAssemblyRefence(typeof(ServiceProviderServiceExtensions).Assembly)
                .AddAssemblyRefence(typeof(Console).Assembly)
                .AddAssemblyRefence(typeof(KadderBuilder).Assembly)
                .AddAssemblyRefence(typeof(GrpcServerOptions).Assembly)
                .AddAssemblyRefence(builder.GetType().Assembly);

                var codeAssembly = codeBuilder.BuildAsync().Result;
                foreach (var servicerProxyer in codeBuilder.Classes)
                {
                    var namespaces   = $"{servicerProxyer.Namespace}.{servicerProxyer.Name}";
                    var proxyerType  = codeAssembly.Assembly.GetType(namespaces);
                    var servicerType = proxyerType.GetInterfaces().FirstOrDefault();
                    if (servicerType == null)
                    {
                        services.AddSingleton(proxyerType);
                    }
                    else
                    {
                        services.AddSingleton(servicerType, proxyerType);
                    }
                }

                foreach (var proxyerOptions in client.ProxyerOptions)
                {
                    foreach (var interceptor in proxyerOptions.Interceptors)
                    {
                        services.AddSingleton(interceptor);
                    }
                }

                services.AddSingleton(client);
                services.AddSingleton <IBinarySerializer, ProtobufBinarySerializer>();
                services.AddSingleton <ServicerInvoker>();
                services.AddSingleton <IObjectProvider, ObjectProvider>();

                var provider = services.BuildServiceProvider();
                KadderOptions.KadderObjectProvider = provider.GetService <IObjectProvider>();
            });
            return(hostBuilder);
        }
Esempio n. 2
0
        public IDictionary <Type, string> GenerateHandler(
            GrpcOptions options,
            GrpcClient client,
            ref CodeBuilder codeBuilder)
        {
            var types = RefelectionHelper.GetImplInterfaceTypes(
                typeof(IMessagingServicer), true, options.GetScanAssemblies());
            var grpcServiceDic = new Dictionary <Type, string>();

            foreach (var typeService in types)
            {
                var className       = typeService.Name.Remove(0, 1);
                var classDescripter = new ClassDescripter(
                    className,
                    codeBuilder.Namespace)
                                      .SetBaseType(typeService.Name)
                                      .AddUsing("System.Threading.Tasks", typeService.Namespace)
                                      .AddUsing("Kadder")
                                      .SetAccess(AccessType.Public);
                grpcServiceDic.Add(typeService, $"{codeBuilder.Namespace}.{className}");

                var baseInterfaces = typeService.GetInterfaces();
                foreach (var method in typeService.GetMethods())
                {
                    var notGrpcMethodCount = method.CustomAttributes
                                             .Count(p =>
                                                    p.AttributeType == typeof(NotGrpcMethodAttribute));
                    if (notGrpcMethodCount > 0)
                    {
                        continue;
                    }

                    var parameters = method.GetParameters();
                    if (parameters.Length != 1)
                    {
                        continue;
                    }

                    var requestName  = parameters[0].ParameterType.Name.ToLower();
                    var responseType = GetMethodReturn(method.ReturnType);
                    var methodName   = method.Name.Replace("Async", "");
                    classDescripter.CreateMember(
                        new MethodDescripter(method.Name, true)
                        .SetAccess(AccessType.Public)
                        .SetReturn($"Task<{responseType.Name}>")
                        .SetParams(
                            new ParameterDescripter(
                                parameters[0].ParameterType.Name, requestName))
                        .AppendCode($@"var client=GrpcClientExtension.ClientDic[""{client.ID.ToString()}""];")
                        .AppendCode($@"return await client.CallAsync<{parameters[0].ParameterType.Name},{responseType.Name}>({requestName}, ""{methodName}"");"))
                    .AddUsing(responseType.Namespace)
                    .AddUsing(parameters[0].ParameterType.Namespace);
                }
                codeBuilder.CreateClass(classDescripter)
                .AddAssemblyRefence(typeService.Assembly.Location);
            }
            codeBuilder.AddAssemblyRefence(this.GetType().Assembly.Location);
            return(grpcServiceDic);
        }
Esempio n. 3
0
        private void GenerateGrpcCallCode(MethodInfo method, RpcParameterInfo parameter, string namespaceName,
                                          CodeBuilder codeBuilder, ref StringBuilder bindServicesCode)
        {
            bindServicesCode.AppendLine($@"
                .AddMethod(new Method<{parameter.ParameterType.Name}, {GrpcServiceBuilder.GetMethodReturn(method).Name}>(
                    MethodType.Unary,
                    ""{namespaceName}.{method.DeclaringType.Name}"",
                    ""{method.Name.Replace("Async", "")}"",
                    new Marshaller<{parameter.ParameterType.Name}>(
                        _binarySerializer.Serialize,
                        _binarySerializer.Deserialize<{parameter.ParameterType.Name}>
                    ),
                    new Marshaller<{GrpcServiceBuilder.GetMethodReturn(method).Name}>(
                        _binarySerializer.Serialize,
                        _binarySerializer.Deserialize<{GrpcServiceBuilder.GetMethodReturn(method).Name}>)
                    ),
                    {method.Name.Replace("Async", "")})");

            codeBuilder
            .AddAssemblyRefence(parameter.ParameterType.Assembly)
            .AddAssemblyRefence(GrpcServiceBuilder.GetMethodReturn(method).Assembly);
        }
        public IDictionary <Type, string> GenerateHandler(
            GrpcOptions options, GrpcClient client, ref CodeBuilder codeBuilder)
        {
            var types          = options.GetKServicers();
            var grpcServiceDic = new Dictionary <Type, string>();

            foreach (var typeService in types)
            {
                var className       = $"{typeService.Name}GrpcService";
                var classDescripter = new ClassDescripter(className, codeBuilder.Namespace)
                                      .SetBaseType(typeService.Name)
                                      .AddUsing("System.Threading.Tasks", typeService.Namespace)
                                      .AddUsing("Kadder")
                                      .SetAccess(AccessType.Public);
                grpcServiceDic.Add(typeService, $"{codeBuilder.Namespace}.{className}");

                var baseInterfaces = typeService.GetInterfaces();
                foreach (var method in typeService.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                {
                    var notGrpcMethodCount = method.CustomAttributes.Count(
                        p => p.AttributeType == typeof(NotGrpcMethodAttribute));
                    if (notGrpcMethodCount > 0)
                    {
                        continue;
                    }

                    var parameters = RpcParameterInfo.Convert(method.GetParameters());
                    if (parameters.Count == 0)
                    {
                        var emptyMessageType = typeof(EmptyMessage);
                        parameters.Add(new RpcParameterInfo()
                        {
                            Name          = emptyMessageType.Name,
                            ParameterType = emptyMessageType,
                            IsEmpty       = true
                        });
                    }

                    var requestName    = parameters[0].ParameterType.Name.ToLower();
                    var responseType   = GetMethodReturn(method);
                    var returnTypeCode = $"new Task<{responseType.Name}>";
                    var returnCode     = "return ";
                    var requestCode    = requestName;
                    if (parameters[0].IsEmpty)
                    {
                        requestCode = "new EmptyMessage()";
                    }
                    if (responseType.IsEmpty)
                    {
                        returnTypeCode = $"new {method.ReturnType.Name}";
                        returnCode     = string.Empty;
                    }
                    var methodName       = method.Name.Replace("Async", "");
                    var methodDescripter = new MethodDescripter(method.Name, true)
                                           .SetAccess(AccessType.Public)
                                           .SetReturn(returnTypeCode)
                                           .AppendCode($@"var client = GrpcClientExtension.ClientDic[""{client.ID.ToString()}""];")
                                           .AppendCode($@"{returnCode}await client.CallAsync<{parameters[0].ParameterType.Name},{responseType.Name}>({requestCode}, ""{methodName}"", ""{typeService.Name}"");");
                    if (!parameters[0].IsEmpty)
                    {
                        methodDescripter.SetParams(new ParameterDescripter(parameters[0].ParameterType.Name, requestName));
                    }
                    classDescripter.CreateMember(methodDescripter)
                    .AddUsing(responseType.Namespace).AddUsing(parameters[0].ParameterType.Namespace);
                }
                codeBuilder.CreateClass(classDescripter)
                .AddAssemblyRefence(typeService.Assembly.Location);
            }
            codeBuilder.AddAssemblyRefence(this.GetType().Assembly.Location);
            return(grpcServiceDic);
        }
Esempio n. 5
0
        public static IHostBuilder UseGrpcServer(this IHostBuilder hostBuilder, Action <HostBuilderContext, IServiceCollection, GrpcServerBuilder> builderAction = null, string configurationKeyName = "GrpcServer")
        {
            hostBuilder.ConfigureServices((context, services) =>
            {
                var log = services.BuildServiceProvider().GetService <ILogger <GrpcServerBuilder> >();

                var builder = context.Configuration.GetSection(configurationKeyName).Get <GrpcServerBuilder>() ?? new GrpcServerBuilder();
                builderAction?.Invoke(context, services, builder);

                var server = new Server(builder.Options.ChannelOptions);
                foreach (var port in builder.Options.Ports)
                {
                    server.Ports.Add(new ServerPort(port.Host, port.Port, port.Credentials));
                }
                foreach (var interceptor in builder.Interceptors)
                {
                    services.AddSingleton(interceptor);
                }

                foreach (var assemblyName in builder.AssemblyNames)
                {
                    builder.Assemblies.Add(Assembly.Load(assemblyName));
                }
                builder.Assemblies.Add(Assembly.GetEntryAssembly());

                if (log.IsEnabled(LogLevel.Debug))
                {
                    log.LogDebug(builder.ToString());
                }

                var servicerTypes = ServicerHelper.GetServicerTypes(builder.Assemblies);
                if (servicerTypes == null || servicerTypes.Count == 0)
                {
                    throw new ArgumentNullException("Not found any grpc servicer!");
                }

                var servicerProxyers = new ServicerProxyGenerator(builder.Options.PackageName, servicerTypes).Generate();

                var codeBuilder = new CodeBuilder("Kadder.Grpc.Server");
                codeBuilder.CreateClass(servicerProxyers.ToArray());
                codeBuilder.AddAssemblyRefence(Assembly.GetExecutingAssembly())
                .AddAssemblyRefence(typeof(ILogger).Assembly)
                .AddAssemblyRefence(typeof(ServerServiceDefinition).Assembly)
                .AddAssemblyRefence(typeof(ServiceProviderServiceExtensions).Assembly)
                .AddAssemblyRefence(typeof(Console).Assembly)
                .AddAssemblyRefence(servicerTypes.Select(p => p.Assembly).Distinct().ToArray())
                .AddAssemblyRefence(typeof(KadderBuilder).Assembly)
                .AddAssemblyRefence(typeof(GrpcServerOptions).Assembly)
                .AddAssemblyRefence(builder.GetType().Assembly);

                var codeAssembly = codeBuilder.BuildAsync().Result;
                foreach (var servicerProxyer in servicerProxyers)
                {
                    var namespaces  = $"{servicerProxyer.Namespace}.{servicerProxyer.Name}";
                    var proxyerType = codeAssembly.Assembly.GetType(namespaces);
                    services.AddSingleton(proxyerType);
                    builder.GrpcServicerProxyers.Add(proxyerType);
                }

                services.AddSingleton(server);
                services.AddSingleton(builder);
                services.AddSingleton <IBinarySerializer, ProtobufBinarySerializer>();
                services.AddSingleton(typeof(KadderBuilder), builder);
                services.AddSingleton <IObjectProvider, ObjectProvider>();
            });
            return(hostBuilder);
        }
Esempio n. 6
0
        private static MethodDescripter GenerateNoGrpcMethod(MethodInfo method, ClassDescripter classDescripter, CodeBuilder codeBuilder)
        {
            var methodDescripter = new MethodDescripter(method.Name)
                                   .SetAccess(AccessType.Public)
                                   .SetReturn(GetReturnName(method.ReturnType))
                                   .AppendCode("throw new System.NotImplementedException();");
            var parameterDescripters = new List <ParameterDescripter>();

            foreach (var param in method.GetParameters())
            {
                parameterDescripters.Add(new ParameterDescripter(GetReturnName(param.ParameterType), param.Name));
                codeBuilder.AddAssemblyRefence(param.ParameterType.Assembly);
            }
            methodDescripter.SetParams(parameterDescripters.ToArray());

            return(methodDescripter);

            string GetReturnName(Type type)
            {
                codeBuilder.AddAssemblyRefence(type.Assembly);

                if (type.IsGenericType)
                {
                    var typeName = $"{type.FullName.Split('`')[0]}<";
                    foreach (var itemType in type.GenericTypeArguments)
                    {
                        typeName += $"{GetReturnName(itemType)},";
                    }
                    return($"{typeName.Remove(typeName.Length-1)}>");
                }
                else if (type.IsValueType || type.Name.StartsWith("String"))
                {
                    switch (type.Name)
                    {
                    case "Int16": return("short");

                    case "Int32": return("int");

                    case "Int64": return("long");

                    case "UInt16": return("ushort");

                    case "UInt32": return("uint");

                    case "UInt64": return("ulong");

                    case "String": return("string");

                    case "Double": return("double");

                    case "Single": return("float");

                    case "Decimal": return("decimal");

                    case "Boolean": return("bool");

                    default: return(string.Empty);
                    }
                }
                else
                {
                    return(type.FullName);
                }
            }
        }
Esempio n. 7
0
        public List <ClassDescripter> GenerateGrpcProxy(GrpcServerOptions options, CodeBuilder codeBuilder = null)
        {
            if (codeBuilder == null)
            {
                codeBuilder = CodeBuilder.Default;
            }
            var implInterfaceTypes  = options.GetKServicers();
            var classDescripterList = new List <ClassDescripter>();
            var protoMessageCode    = new StringBuilder();
            var protoServiceCode    = new StringBuilder();

            foreach (Type service in implInterfaceTypes)
            {
                var bindServicesCode = new StringBuilder("return ServerServiceDefinition.CreateBuilder()\n");
                protoServiceCode.AppendLine($"service {service.Name} {{");
                var @class     = this.GenerateGrpcService(service);
                var interfaces = service.GetInterfaces();
                foreach (var method in service.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                {
                    if (method.CustomAttributes.FirstOrDefault(p => p.AttributeType == typeof(NotGrpcMethodAttribute)) != null)
                    {
                        continue;
                    }
                    var parameters = RpcParameterInfo.Convert(method.GetParameters());
                    if (parameters.Count == 0)
                    {
                        var emptyMessageType = typeof(EmptyMessage);
                        parameters.Add(new RpcParameterInfo()
                        {
                            Name          = emptyMessageType.Name,
                            ParameterType = emptyMessageType,
                            IsEmpty       = true
                        });
                    }

                    @class = GenerateGrpcMethod(@class, method, parameters[0], interfaces);
                    GenerateGrpcCallCode(method, parameters[0], options.NamespaceName, codeBuilder, ref bindServicesCode);
                    GenerateGrpcCallCodeForOldVersion(method, parameters[0], options.NamespaceName, options.ServiceName, codeBuilder, ref bindServicesCode);
                    if (options.IsGeneralProtoFile)
                    {
                        GenerateProtoCode(method, parameters[0], ref protoServiceCode, ref protoMessageCode);
                    }
                }
                bindServicesCode.AppendLine(".Build();");
                protoServiceCode.AppendLine();
                protoServiceCode.AppendLine("}");
                @class.CreateMember(new MethodDescripter("BindServices", false).SetCode(bindServicesCode.ToString()).SetReturn("ServerServiceDefinition").SetAccess(AccessType.Public));
                codeBuilder.AddAssemblyRefence(Assembly.GetExecutingAssembly())
                .AddAssemblyRefence(typeof(ServerServiceDefinition).Assembly)
                .AddAssemblyRefence(typeof(ServerServiceDefinition).Assembly)
                .AddAssemblyRefence(typeof(ServiceProviderServiceExtensions).Assembly)
                .AddAssemblyRefence(typeof(Console).Assembly)
                .AddAssemblyRefence(service.Assembly);
                codeBuilder.CreateClass(@class);
                classDescripterList.Add(@class);
            }
            if (options.IsGeneralProtoFile)
            {
                if (string.IsNullOrWhiteSpace(options.PackageName))
                {
                    options.PackageName = options.NamespaceName;
                }

                var stringBuilder = new StringBuilder();
                stringBuilder.AppendLine("syntax = \"proto3\";");
                stringBuilder.AppendLine($@"option csharp_namespace = ""{options.NamespaceName}"";");
                stringBuilder.AppendLine($"package {options.PackageName};\n");
                stringBuilder.Append(protoServiceCode);
                stringBuilder.AppendLine();
                var messageCode = protoMessageCode.ToString();
                if (messageCode.Contains(".bcl."))
                {
                    protoMessageCode.Replace(".bcl.", "");
                    protoMessageCode.AppendLine(Bcl.Proto);
                }
                stringBuilder.Append(protoMessageCode);
                var path = $"{Environment.CurrentDirectory}/{options.NamespaceName}.proto";
                if (File.Exists(path))
                {
                    File.Delete(path);
                }

                File.WriteAllText(path, stringBuilder.ToString());
                _messages = null;
            }
            return(classDescripterList);
        }
Esempio n. 8
0
        public ClassDescripter GenerateHandlerProxy(
            Assembly[] assemblies, CodeBuilder codeBuilder = null)
        {
            if (codeBuilder == null)
            {
                codeBuilder = CodeBuilder.Default;
            }

            var types = RefelectionHelper.GetImplInterfaceTypes(
                typeof(IMessagingServicer), true, assemblies);

            var codeClass = new ClassDescripter("MessageServicerProxy", "Kadder")
                            .SetAccess(AccessType.Public)
                            .SetBaseType("IMessageServicerProxy")
                            .AddUsing(
                "using System;",
                "using Kadder.Utilies;",
                "using System.Threading.Tasks;",
                "using Microsoft.Extensions.DependencyInjection;");

            var needResult = new StringBuilder();
            var noResult   = new StringBuilder();

            foreach (var type in types)
            {
                var methods = type.GetMethods();
                foreach (var method in methods)
                {
                    var parameters = method.GetParameters();
                    if (parameters.Length != 1)
                    {
                        continue;
                    }
                    var requestName = GetRequestName(method);
                    if (method.ReturnType == typeof(void))
                    {
                        noResult.AppendLine(
                            $@"if(string.Equals(message.GetTypeFullName(),""{requestName}""))
                               {{
                                   return async (m)=>await {{serviceProvider.GetService<{type.Name}>().{method.Name}(message as {parameters[0].ParameterType.FullName});}} ;   
                               }}");
                    }
                    else
                    {
                        needResult.AppendLine(
                            $@"if(string.Equals(message.GetTypeFullName(),""{requestName}""))
                               {{
                                   return async (m)=>{{return (await serviceProvider.GetService<{type.Name}>().{method.Name}(message as {parameters[0].ParameterType.FullName})) as TMessageResult;}} ;   
                               }}");
                    }
                    codeBuilder.AddAssemblyRefence(parameters[0].ParameterType.Assembly.Location);
                }
                codeClass.AddUsing($"using {type.Namespace};");
                codeBuilder.AddAssemblyRefence(type.Assembly.Location);
            }

            noResult.Append("return null;");
            needResult.Append("return null;");

            codeClass.CreateMember(
                new MethodDescripter("GetHandleDelegate<TMessage,TMessageResult>")
                .SetAccess(AccessType.Public)
                .SetReturn("Func<TMessage,Task<TMessageResult>>")
                .SetCode(needResult.ToString())
                .SetParams(
                    new ParameterDescripter("TMessage", "message"),
                    new ParameterDescripter("IServiceProvider", "serviceProvider"))
                .SetTypeParameters(
                    new TypeParameterDescripter("TMessageResult", "class"),
                    new TypeParameterDescripter("TMessage", "BaseMessage")),
                new MethodDescripter("GetHandleDelegate<TMessage>")
                .SetAccess(AccessType.Public)
                .SetReturn("Func<TMessage,Task>")
                .SetCode(noResult.ToString())
                .SetParams(
                    new ParameterDescripter("TMessage", "message"),
                    new ParameterDescripter("IServiceProvider", "serviceProvider"))
                .SetTypeParameters(
                    new TypeParameterDescripter("TMessage", "BaseMessage")));

            codeBuilder
            .AddAssemblyRefence(assemblies.Select(p => p.Location).ToArray())
            .AddAssemblyRefence(Assembly.GetExecutingAssembly().Location)
            .AddAssemblyRefence(typeof(ServiceProviderServiceExtensions).Assembly.Location)
            .CreateClass(codeClass);

            return(codeClass);
        }
Esempio n. 9
0
        public ClassDescripter GenerateGrpcProxy(
            GrpcServerOptions options, CodeBuilder codeBuilder = null)
        {
            if (codeBuilder == null)
            {
                codeBuilder = CodeBuilder.Default;
            }

            var types = RefelectionHelper.GetImplInterfaceTypes(
                typeof(IMessagingServicer), true, options.GetScanAssemblies());

            var codeClass = new ClassDescripter("GrpcService", "Kadder")
                            .SetAccess(AccessType.Public)
                            .SetBaseType("IGrpcServices")
                            .AddUsing("using Grpc.Core;")
                            .AddUsing("using System.Threading.Tasks;")
                            .AddUsing("using Kadder;")
                            .AddUsing("using Kadder.Utilies;")
                            .AddUsing("using Microsoft.Extensions.DependencyInjection;")
                            .CreateFiled(
                new FieldDescripter("_binarySerializer")
                .SetAccess(AccessType.PrivateReadonly)
                .SetType(typeof(IBinarySerializer)),
                new FieldDescripter("_messageServicer")
                .SetAccess(AccessType.PrivateReadonly)
                .SetType(typeof(GrpcMessageServicer)))
                            .CreateConstructor(
                new ConstructorDescripter("GrpcService")
                .SetCode("_binarySerializer=GrpcServerBuilder.ServiceProvider.GetService<IBinarySerializer>();\n_messageServicer=GrpcServerBuilder.ServiceProvider.GetService<GrpcMessageServicer>();")
                .SetAccess(AccessType.Public));

            var bindServicesCode = new StringBuilder("return ServerServiceDefinition.CreateBuilder()\n");
            var protoServiceCode = new StringBuilder($"service {options.ServiceName} {{");
            var protoMessageCode = new StringBuilder();

            protoServiceCode.AppendLine();
            foreach (var item in types)
            {
                var baseInterfaces = item.GetInterfaces();
                foreach (var method in item.GetMethods())
                {
                    if (method.CustomAttributes.FirstOrDefault(p => p.AttributeType == typeof(NotGrpcMethodAttribute)) != null)
                    {
                        continue;
                    }
                    var parameters = method.GetParameters();
                    if (parameters.Length != 1)
                    {
                        continue;
                    }
                    CreateCallCode(method, parameters[0], baseInterfaces);
                    CreateGrpcCallCode(method, parameters[0]);

                    if (options.IsGeneralProtoFile)
                    {
                        CreateProtoCode(method, parameters[0]);
                    }
                }
            }
            bindServicesCode.AppendLine(".Build();");
            codeClass.CreateMember(
                new MethodDescripter("BindServices")
                .SetCode(bindServicesCode.ToString())
                .SetReturn("ServerServiceDefinition")
                .SetAccess(AccessType.Public));
            codeBuilder.AddAssemblyRefence(Assembly.GetExecutingAssembly().Location)
            .AddAssemblyRefence(typeof(ServerServiceDefinition).Assembly.Location)
            .AddAssemblyRefence(typeof(ServerServiceDefinition).Assembly.Location)
            .AddAssemblyRefence(typeof(ServiceProviderServiceExtensions).Assembly.Location);

            if (options.IsGeneralProtoFile)
            {
                protoServiceCode.Append("\n}\n");
                var protoStr = new StringBuilder();
                protoStr.AppendLine(@"syntax = ""proto3"";");
                protoStr.AppendLine($@"option csharp_namespace = ""{options.NamespaceName}"";");
                protoStr.AppendLine($"package {options.PackageName};\n");
                protoStr.Append(protoServiceCode);
                protoStr.AppendLine();
                protoStr.Append(protoMessageCode);
                var fileName = $"{Environment.CurrentDirectory}/{options.NamespaceName}.proto";
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }
                File.WriteAllText(fileName, protoStr.ToString());
                _messages = null;
            }

            codeBuilder.CreateClass(codeClass);

            return(codeClass);

            void CreateCallCode(MethodInfo method, ParameterInfo parameter, Type[] baseInterfaces)
            {
                var requestName = GetRequestName(method);

                codeClass
                .CreateMember(
                    new MethodDescripter($"{method.Name.Replace("Async", "")}", true)
                    .AppendCode(
                        $@"request.SetTypeFullName(""{requestName}"");
                            return await _messageServicer.ProcessAsync<{parameter.ParameterType.Name},{GetMethodReturn(method.ReturnType).Name}>(request,context);")
                    .SetReturn($"Task<{GetMethodReturn(method.ReturnType).Name}>")
                    .SetParams(
                        new ParameterDescripter(parameter.ParameterType.Name, "request"),
                        new ParameterDescripter("ServerCallContext", "context"))
                    .SetAccess(AccessType.Public))
                .AddUsing($"using {parameter.ParameterType.Namespace};")
                .AddUsing($"using {GetMethodReturn(method.ReturnType).Namespace};");
            }

            void CreateGrpcCallCode(MethodInfo method, ParameterInfo parameter)
            {
                bindServicesCode.AppendLine($@".AddMethod(new Method<{parameter.ParameterType.Name},{GetMethodReturn(method.ReturnType).Name}>(
                                            MethodType.Unary,
                                            ""{options.NamespaceName}.{options.ServiceName}"",
                                            ""{method.Name.Replace("Async", "")}"",
                                            new Marshaller<{parameter.ParameterType.Name}>(
                                                _binarySerializer.Serialize,
                                                _binarySerializer.Deserialize<{parameter.ParameterType.Name}>
                                            ),
                                            new Marshaller<{GetMethodReturn(method.ReturnType).Name}>(
                                                _binarySerializer.Serialize,
                                                _binarySerializer.Deserialize<{GetMethodReturn(method.ReturnType).Name}>)
                                            ),
                                        {method.Name.Replace("Async", "")})");
                codeBuilder.AddAssemblyRefence(parameter.ParameterType.Assembly.Location)
                .AddAssemblyRefence(GetMethodReturn(method.ReturnType).Assembly.Location);
            }

            void CreateProtoCode(MethodInfo method, ParameterInfo parameter)
            {
                protoServiceCode.AppendLine();
                protoServiceCode.AppendLine($"\trpc {method.Name.Replace("Async", "")}({parameter.ParameterType.Name}) returns({GetMethodReturn(method.ReturnType).Name});");
                if (!_messages.Contains(parameter.ParameterType.Name))
                {
                    protoMessageCode.AppendLine(CreateProtoMessageCode(parameter.ParameterType));
                    _messages.Add(parameter.ParameterType.Name);
                }
                if (!_messages.Contains(GetMethodReturn(method.ReturnType).Name))
                {
                    protoMessageCode.AppendLine(CreateProtoMessageCode(GetMethodReturn(method.ReturnType)));
                    _messages.Add(GetMethodReturn(method.ReturnType).Name);
                }
            }

            string CreateProtoMessageCode(Type messageType)
            {
                //    Serializer.GetProto(messageType);

                if (_messages.Contains(messageType.Name))
                {
                    return("");
                }

                var messageCode = new StringBuilder($"message {messageType.Name} {{");
                var enumCode    = new StringBuilder();
                var refenceCode = new StringBuilder();

                messageCode.AppendLine();
                var properties      = messageType.GetProperties().Where(p => p.DeclaringType == messageType);
                var isNeedAutoIndex = !(properties.FirstOrDefault(p => p.GetCustomAttribute(typeof(ProtoMemberAttribute)) != null) != null);
                int index           = 1;

                foreach (var item in properties.OrderBy(p => p.Name, new ProtoPropertyCompare()))
                {
                    if (item.GetCustomAttribute(typeof(ProtoIgnoreAttribute)) != null)
                    {
                        continue;
                    }
                    if (!isNeedAutoIndex)
                    {
                        var memberAttribute = item.GetCustomAttribute <ProtoMemberAttribute>();
                        if (memberAttribute == null)
                        {
                            continue;
                        }
                        messageCode.Append($"\t{GetFiledType(item.PropertyType)} {item.Name} = {memberAttribute.Tag};\n");
                    }
                    else
                    {
                        if (item.GetCustomAttribute(typeof(ProtoIgnoreAttribute)) != null)
                        {
                            continue;
                        }
                        messageCode.Append($"\t{GetFiledType(item.PropertyType)} {item.Name} = {index};\n");
                        index++;
                    }

                    if (!item.PropertyType.IsGenericType && string.Equals(item.PropertyType.BaseType.Name.ToLower(), "enum") && !_messages.Contains(item.PropertyType.Name))
                    {
                        GeneralEnumCode(item.PropertyType);
                        _messages.Add(item.PropertyType.Name);
                    }

                    if (item.PropertyType.IsClass && item.PropertyType.GetCustomAttribute <ProtoContractAttribute>() != null)
                    {
                        refenceCode.AppendLine(CreateProtoMessageCode(item.PropertyType));
                    }
                    if (item.PropertyType.IsArray && item.PropertyType.GetElementType().GetCustomAttribute <ProtoContractAttribute>() != null)
                    {
                        refenceCode.AppendLine(CreateProtoMessageCode(item.PropertyType.GetElementType()));
                    }
                }
                _messages.Add(messageType.Name);
                return(messageCode.Append("}\n\n").Append(enumCode).Append(refenceCode).ToString());

                string GetFiledType(Type type)
                {
                    switch (type.Name.ToLower())
                    {
                    case "int": return("int32");

                    case "int32": return("int32");

                    case "int64": return("int64");

                    case "long": return("int64");

                    case "string": return("string");

                    case "datetime": return("bcl.DateTime");

                    case "bool": return("bool");

                    case "boolean": return("bool");

                    case "double": return("double");

                    case "float": return("float");

                    default:
                        if (type.Name.Contains("[]"))
                        {
                            return($"repeated {GetFiledType(type.GetElementType())}");
                        }
                        return(type.Name);
                    }
                }

                void GeneralEnumCode(Type type)
                {
                    var zeroCode      = "\tZERO = 0;";
                    var enumFiledCode = new StringBuilder();
                    var hasDefault    = false;

                    foreach (var item in type.GetFields())
                    {
                        if (item.Name.Equals("value__"))
                        {
                            continue;
                        }
                        var values = (int)item.GetValue(null);
                        if (values <= 0)
                        {
                            hasDefault = true;
                        }
                        enumFiledCode.AppendLine($"\t{item.Name} = {values};");
                    }
                    if (hasDefault)
                    {
                        enumCode.Append($"enum {type.Name}{{\n{enumFiledCode}}}\n");
                    }
                    else
                    {
                        enumCode.Append($"enum {type.Name}{{\n{zeroCode}\n{enumFiledCode}}}\n");
                    }
                }
            }
        }