private ClassDescripter generateClass(Type servicerType) { var servicerName = $"KadderServer{servicerType.Name}"; var namespaceName = servicerType.Namespace; if (!string.IsNullOrWhiteSpace(_packageName)) { namespaceName = _packageName; } var classDescripter = new ClassDescripter(servicerName, namespaceName) .SetBaseType(typeof(IGrpcServices).Name) .AddUsing(typeof(IGrpcServices).Namespace) .AddUsing( "using Grpc.Core;", "using System.Threading.Tasks;", "using Kadder;", "using Kadder.Utilies;", "using Kadder.Utils;", "using Microsoft.Extensions.DependencyInjection;", "using Kadder.Messaging;"); classDescripter.SetAccess(AccessType.Public); return(classDescripter); }
private MethodDescripter generateBindServicesMethod(ref ClassDescripter classDescripter, Type servicerType) { var bindServicesMethod = new MethodDescripter("BindServices", classDescripter); bindServicesMethod.Access = AccessType.Public; bindServicesMethod.SetReturnType(typeof(ServerServiceDefinition)); bindServicesMethod.AppendCode(@"return ServerServiceDefinition.CreateBuilder()"); foreach (var method in classDescripter.Methods) { if (method.Attributes.Count == 0) { continue; } var fakeMethodTypeAttribute = method.Attributes.FirstOrDefault(p => p.Name == FakeCallTypeAttributeName); if (fakeMethodTypeAttribute == null) { continue; } var callType = (CallType)int.Parse(fakeMethodTypeAttribute.Parameters[0]); bindServicesMethod.AppendCode(generateBindServicesCode(classDescripter, method, callType, servicerType)); method.Attributes.Remove(fakeMethodTypeAttribute); } bindServicesMethod.AppendCode(@" .Build();"); return(bindServicesMethod); }
private MethodDescripter generateMethodHead(ref ClassDescripter classDescripter, MethodInfo methodInfo, bool isAsync = true) { var method = new MethodDescripter(methodInfo.Name, classDescripter, isAsync); method.Access = AccessType.Public; return(method); }
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); }
private MethodDescripter generateBindServicesMethod(ref ClassDescripter classDescripter) { var bindServicesMethod = new MethodDescripter("BindServices", classDescripter); bindServicesMethod.Access = AccessType.Public; bindServicesMethod.SetReturnType(typeof(ServerServiceDefinition)); bindServicesMethod.AppendCode(@"throw new NotImplementedException();"); return(bindServicesMethod); }
private string CreateAndGetDirFromNamespace(ClassDescripter _class, string prefix) { var dirPath = Path.Combine(prefix, _class.Namespace.Replace(".", "/")); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } return(dirPath); }
private void generateField(ref ClassDescripter classDescripter) { var invokerField = new FieldDescripter(ClassServicerInvokerName) .SetType(typeof(ServicerInvoker)); invokerField.SetAccess(AccessType.PrivateReadonly); classDescripter.CreateFiled(invokerField) .AddUsing(typeof(ServicerInvoker).Namespace); }
public void CodeSavePath_Test() { var codeBuilder = new CodeBuilder("test", "GenAssembly.Test"); var codeClass = new ClassDescripter("Person", namespaces: "GenAssembly.Test").AddUsing("System"); codeClass.CreateMember( new MethodDescripter("Hello", codeClass) .SetAccess(AccessType.Public) .SetReturnType("void") .AppendCode("Console.WriteLine(\"Hello\");")); codeBuilder.CreateClass(codeClass); codeBuilder.BuildAsync().Wait(); Assert.True(File.Exists(Path.Combine(CodeBuilder.CodeCachePath, "GenAssembly/Test/Person.cs"))); }
private string GetReturnName(ref ClassDescripter classDescripter, Type type) { classDescripter.AddUsing(type.Namespace); if (type.IsGenericType) { var typeName = $"{type.FullName.Split('`')[0]}<"; foreach (var itemType in type.GenericTypeArguments) { typeName += $"{GetReturnName(ref classDescripter, 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); } }
private MethodDescripter generateRpcMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo, Type parameterType, Type returnType) { var resultCode = Helper.GenerateAwaitResultCode(returnType); var requestCode = Helper.GenerateRequestCode(parameterType); var servicerName = methodInfo.DeclaringType.FullName; var methodName = methodInfo.Name; var returnCode = Helper.GenerateReturnCode(returnType); var method = generateMethodHead(ref classDescripter, methodInfo); method.Parameters.Add(new ParameterDescripter(parameterType.Name, "request")); method.Parameters.Add(new ParameterDescripter("ServerCallContext", "context")); method.AppendCode(genCallCode(servicerName, methodName, resultCode, requestCode, returnCode)); method.SetReturnType($"Task<{returnType.Name}>"); return(method); }
private void generateConstructor(ref ClassDescripter classDescripter) { var constructor = new ConstructorDescripter(classDescripter.Name); constructor.SetAccess(AccessType.Public); var providerParameter = new ParameterDescripter(typeof(ServicerInvoker).Name, "invoker"); constructor.SetParams(providerParameter); var code = $@" {ClassServicerInvokerName} = invoker;"; constructor.SetCode(code); classDescripter.CreateConstructor(constructor); }
private MethodDescripter generateDuplexStreamRpcMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo, Type parameterType, Type returnType) { var servicerName = getServicerName(methodInfo.DeclaringType); var methodName = methodInfo.Name.Replace("Async", ""); var requestType = parameterType.GenericTypeArguments[0]; var responseType = returnType.GenericTypeArguments[0]; var method = generateMethodHead(ref classDescripter, methodInfo, false); method.Parameters.Add(new ParameterDescripter($"IAsyncRequestStream<{requestType.Name}>", "request")); method.Parameters.Add(new ParameterDescripter($"IAsyncResponseStream<{responseType.Name}>", "response")); method.AppendCode($@"return {ClassServicerInvokerName}.DuplexStreamAsync<{requestType.Name}, {responseType.Name}>(request, response, ""{servicerName}"", ""{methodName}"");"); method.SetReturnType("Task"); return(method); }
private MethodDescripter generateClientStreamRpcMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo, Type parameterType, Type returnType) { var servicerName = getServicerName(methodInfo.DeclaringType); var resultCode = Helper.GenerateAwaitResultCode(returnType); var resultType = generateRpcResponseType(returnType); var methodName = methodInfo.Name.Replace("Async", ""); var requestType = parameterType.GenericTypeArguments[0]; var method = generateMethodHead(ref classDescripter, methodInfo, false); method.Parameters.Add(new ParameterDescripter($"IAsyncRequestStream<{requestType.Name}>", "request")); method.AppendCode($@"{resultCode}{ClassServicerInvokerName}.ClientStreamAsync<{requestType.Name}, {returnType.Name}>(request, ""{servicerName}"", ""{methodName}""); {Helper.GenerateReturnCode(returnType, true)}"); method.SetReturnType(resultType); return(method); }
private string generateBindServicesCode(ClassDescripter @class, MethodDescripter method, CallType callType, Type servicerType) { var callInfo = getCallInfo(callType, method); callInfo.RequestType = callInfo.RequestType.Replace("IAsyncStreamReader<", "").Replace("Task<", "").Replace(">", ""); callInfo.ResponseType = callInfo.ResponseType.Replace("IServerStreamWriter<", "").Replace("Task<", "").Replace(">", ""); var code = new StringBuilder(); code.Append($@" .AddMethod(new Method<{callInfo.RequestType}, {callInfo.ResponseType}>( {callInfo.MethodType}, ""{@class.Namespace}.{servicerType.Name}"", ""{method.Name}"", new Marshaller<{callInfo.RequestType}>( {ClassBinarySerializerName}.Serialize, {ClassBinarySerializerName}.Deserialize<{callInfo.RequestType}> ), new Marshaller<{callInfo.ResponseType}>( {ClassBinarySerializerName}.Serialize, {ClassBinarySerializerName}.Deserialize<{callInfo.ResponseType}> )), {method.Name})"); // This is will be remove, It's use compatible async if (method.Name.EndsWith("Async")) { code.AppendLine(); code.Append($@" .AddMethod(new Method<{callInfo.RequestType}, {callInfo.ResponseType}>( {callInfo.MethodType}, ""{@class.Namespace}.{servicerType.Name}"", ""{method.Name.Replace("Async","")}"", new Marshaller<{callInfo.RequestType}>( {ClassBinarySerializerName}.Serialize, {ClassBinarySerializerName}.Deserialize<{callInfo.RequestType}> ), new Marshaller<{callInfo.ResponseType}>( {ClassBinarySerializerName}.Serialize, {ClassBinarySerializerName}.Deserialize<{callInfo.ResponseType}> )), {method.Name})"); } return(code.ToString()); }
private MethodDescripter generateNoGrpcMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo) { var method = new MethodDescripter(methodInfo.Name, classDescripter, false); method.Access = AccessType.Public; method.SetReturnType(GetReturnName(ref classDescripter, methodInfo.ReturnType)); var parameterDescripters = new List <ParameterDescripter>(); foreach (var param in methodInfo.GetParameters()) { classDescripter.AddUsing(param.ParameterType.Namespace); method.Parameters.Add(new ParameterDescripter(GetReturnName(ref classDescripter, param.ParameterType), param.Name)); } method.AppendCode("throw new System.NotImplementedException();"); return(method); }
private ClassDescripter GenerateGrpcMethod(ClassDescripter @class, MethodInfo method, RpcParameterInfo parameter, Type[] baseInterfaces) { var className = method.DeclaringType.Name; var messageName = parameter.ParameterType.Name; var messageResultType = GrpcServiceBuilder.GetMethodReturn(method); var messageResultName = messageResultType.Name; var requestCode = "messageEnvelope.Message"; var responseCode = "var result = "; var setResponseCode = "result"; if (parameter.IsEmpty) { requestCode = string.Empty; } if (messageResultType.IsEmpty) { responseCode = string.Empty; setResponseCode = "new EmptyMessageResult()"; } var code = $@" var envelope = new MessageEnvelope<{messageName}>(); envelope.Message = request; var grpcContext = new GrpcContext(envelope, context); Func<IMessageEnvelope, IServiceScope, Task<IMessageResultEnvelope>> handler = async (imsgEnvelope, scope) => {{ var messageEnvelope = (MessageEnvelope<{messageName}>) imsgEnvelope; {responseCode}await scope.ServiceProvider.GetService<{className}>().{method.Name}({requestCode}); return new MessageResultEnvelope<{messageResultName}>() {{ MessageResult = {setResponseCode} }}; }}; var resultEnvelope = await _messageServicer.ProcessAsync(grpcContext, handler); return ((MessageResultEnvelope<{messageResultName}>)resultEnvelope).MessageResult;"; return(@class.CreateMember( new MethodDescripter(method.Name.Replace("Async", "") ?? "", true) .SetAccess(AccessType.Public) .AppendCode(code).SetReturn($"Task<{GrpcServiceBuilder.GetMethodReturn(method).Name}>") .SetParams( new ParameterDescripter(parameter.ParameterType.Name, "request"), new ParameterDescripter("ServerCallContext", "context"))) .AddUsing($"using {parameter.ParameterType.Namespace};") .AddUsing($"using {method.DeclaringType.Namespace};") .AddUsing($"using {GrpcServiceBuilder.GetMethodReturn(method).Namespace};")); }
private void generateConstructor(ref ClassDescripter classDescripter) { var constructor = new ConstructorDescripter(classDescripter.Name); constructor.SetAccess(AccessType.Public); var providerParameter = new ParameterDescripter(typeof(IObjectProvider).Name, "provider"); constructor.SetParams(providerParameter); var code = $@" {ClassProviderName} = provider; {ClassBinarySerializerName} = provider.GetObject<IBinarySerializer>(); {ClassLoggerName} = provider.GetObject<ILogger<{classDescripter.Name}>>();"; constructor.SetCode(code); classDescripter.CreateConstructor(constructor); }
private MethodDescripter generateServerStreamRpcMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo, Type parameterType, Type returnType) { var requestCode = $"{Helper.GenerateRequestCode(parameterType)}, responseStream"; var servicerName = methodInfo.DeclaringType.FullName; var responseType = returnType.GenericTypeArguments[0]; var methodName = methodInfo.Name; var method = generateMethodHead(ref classDescripter, methodInfo); method.Parameters.Add(new ParameterDescripter(parameterType.Name, "request")); method.Parameters.Add(new ParameterDescripter($"IServerStreamWriter<{responseType.Name}>", "response")); method.Parameters.Add(new ParameterDescripter("ServerCallContext", "context")); method.AppendCode($"var responseStream = new AsyncResponseStream<{responseType.Name}>(response);"); method.AppendCode(genCallCode(servicerName, methodName, string.Empty, requestCode, string.Empty)); method.SetReturnType("Task"); classDescripter.AddUsing(typeof(IServerStreamWriter <>).Namespace); classDescripter.AddUsing(typeof(AsyncRequestStream <>).Namespace); return(method); }
private ClassDescripter generateClass(Type servicerType) { var servicerName = $"KadderClient{servicerType.Name}"; var namespaceName = getNamespaceName(servicerType); var classDescripter = new ClassDescripter(servicerName, namespaceName) .SetBaseType(servicerType.Name) .AddUsing(servicerType.Namespace) .AddUsing( "using Grpc.Core;", "using System.Threading.Tasks;", "using Kadder;", "using Kadder.Utilies;", "using Kadder.Utils;", "using Microsoft.Extensions.DependencyInjection;", "using Kadder.Messaging;"); classDescripter.SetAccess(AccessType.Public); return(classDescripter); }
private MethodDescripter generateClientStreamRpcMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo, Type parameterType, Type returnType) { var resultCode = Helper.GenerateAwaitResultCode(returnType); var servicerName = methodInfo.DeclaringType.FullName; var methodName = methodInfo.Name; var requestParameterType = parameterType.GenericTypeArguments[0]; var returnCode = Helper.GenerateReturnCode(returnType); var method = generateMethodHead(ref classDescripter, methodInfo); method.Parameters.Add(new ParameterDescripter($"IAsyncStreamReader<{requestParameterType.Name}>", "request")); method.Parameters.Add(new ParameterDescripter("ServerCallContext", "context")); method.AppendCode($"var streamReq = new AsyncRequestStream<{requestParameterType.Name}>(request);"); method.AppendCode(genCallCode(servicerName, methodName, resultCode, "streamReq", returnCode)); method.SetReturnType($"Task<{returnType.Name}>"); classDescripter.AddUsing(typeof(IAsyncStreamReader <>).Namespace); classDescripter.AddUsing(typeof(AsyncRequestStream <>).Namespace); return(method); }
private void generateField(ref ClassDescripter classDescripter) { var binarySerializerField = new FieldDescripter(ClassBinarySerializerName) .SetType(typeof(IBinarySerializer)); binarySerializerField.SetAccess(AccessType.PrivateReadonly); var providerField = new FieldDescripter(ClassProviderName) .SetType(typeof(IObjectProvider)); providerField.SetAccess(AccessType.PrivateReadonly); var loggerField = new FieldDescripter(ClassLoggerName).SetType(typeof(ILogger)); loggerField.SetAccess(AccessType.PrivateReadonly); classDescripter.CreateFiled(binarySerializerField, providerField, loggerField) .AddUsing(typeof(IBinarySerializer).Namespace) .AddUsing(typeof(IObjectProvider).Namespace) .AddUsing(typeof(ILogger).Namespace); }
private MethodDescripter generateMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo) { if (methodInfo.CustomAttributes.FirstOrDefault(p => p.AttributeType == typeof(NotGrpcMethodAttribute)) != null) { return(generateNoGrpcMethod(ref classDescripter, methodInfo)); } var parameterType = methodInfo.ParseMethodParameter(); var returnType = methodInfo.ParseMethodReturnParameter(); var callType = Helper.AnalyseCallType(parameterType, returnType); classDescripter.AddUsing(parameterType.Namespace, returnType.Namespace, methodInfo.DeclaringType.Namespace); var method = new MethodDescripter("", classDescripter); switch (callType) { case CallType.Rpc: method = generateRpcMethod(ref classDescripter, methodInfo, parameterType, returnType); break; case CallType.ClientStreamRpc: method = generateClientStreamRpcMethod(ref classDescripter, methodInfo, parameterType, returnType); break; case CallType.ServerStreamRpc: method = generateServerStreamRpcMethod(ref classDescripter, methodInfo, parameterType, returnType); break; case CallType.DuplexStreamRpc: method = generateDuplexStreamRpcMethod(ref classDescripter, methodInfo, parameterType, returnType); break; default: throw new InvalidOperationException("Invalid Method definition!"); } return(method); }
private MethodDescripter generateServerStreamRpcMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo, Type parameterType, Type returnType) { var servicerName = getServicerName(methodInfo.DeclaringType); var requestCode = Helper.GenerateRequestCode(parameterType); var methodName = methodInfo.Name.Replace("Async", ""); var responseType = returnType.GenericTypeArguments[0]; if (!string.IsNullOrWhiteSpace(requestCode)) { requestCode += ", "; } var method = generateMethodHead(ref classDescripter, methodInfo, false); method.Parameters.Add(new ParameterDescripter(parameterType.Name, "request")); method.Parameters.Add(new ParameterDescripter($"IAsyncResponseStream<{responseType.Name}>", "response")); method.AppendCode($@"return {ClassServicerInvokerName}.ServerStreamAsync<{parameterType.Name}, {responseType.Name}>({requestCode}response, ""{servicerName}"", ""{methodName}"");"); method.SetReturnType("Task"); return(method); }
private MethodDescripter generateMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo) { var parameterType = methodInfo.ParseMethodParameter(); var returnType = methodInfo.ParseMethodReturnParameter(); var callType = Helper.AnalyseCallType(parameterType, returnType); classDescripter.AddUsing(parameterType.Namespace, returnType.Namespace, methodInfo.DeclaringType.Namespace); var method = new MethodDescripter("", classDescripter); switch (callType) { case CallType.Rpc: method = generateRpcMethod(ref classDescripter, methodInfo, parameterType, returnType); break; case CallType.ClientStreamRpc: method = generateClientStreamRpcMethod(ref classDescripter, methodInfo, parameterType, returnType); break; case CallType.ServerStreamRpc: method = generateServerStreamRpcMethod(ref classDescripter, methodInfo, parameterType, returnType); break; case CallType.DuplexStreamRpc: method = generateDuplexStreamRpcMethod(ref classDescripter, methodInfo, parameterType, returnType); break; default: throw new InvalidOperationException("Invalid Method definition!"); } var methodTypeAttribute = new AttributeDescripter(FakeCallTypeAttributeName, ((int)callType).ToString()); method.Attributes.Add(methodTypeAttribute); return(method); }
public void Test_New_Simple_Class() { var classes = new ClassDescripter("User") .SetBaseType(typeof(IUser)) .SetAccess(AccessType.Public) .CreateConstructor( new ConstructorDescripter("User") .SetAccess(AccessType.Public) ) .CreateMember( new MethodDescripter("Hello") .SetAccess(AccessType.Public) .SetCode("return Task.FromResult(\"hello\");") .SetReturn("Task<string>") ) .AddUsing("System.Threading.Tasks"); var assembly = CodeBuilder.Instance.CreateClass(classes) .Build(); var user = (IUser)assembly.Assembly.CreateInstance("Atlantis.Common.CodeGeneration.User"); _output.WriteLine(user.Hello().Result); }
private MethodDescripter generateRpcMethod(ref ClassDescripter classDescripter, MethodInfo methodInfo, Type parameterType, Type returnType) { var resultCode = Helper.GenerateAwaitResultCode(returnType); var resultType = generateRpcResponseType(returnType); var servicerName = getServicerName(methodInfo.DeclaringType); var methodName = methodInfo.Name.Replace("Async", ""); var method = generateMethodHead(ref classDescripter, methodInfo); if (parameterType != typeof(EmptyMessage)) { method.Parameters.Add(new ParameterDescripter(parameterType.Name, "request")); } else { method.AppendCode("var request = new EmptyMessage();"); } method.AppendCode($@"{resultCode} await {ClassServicerInvokerName}.RpcAsync<{parameterType.Name}, {returnType.Name}>(request, ""{servicerName}"", ""{methodName}""); {Helper.GenerateReturnCode(returnType, true)}"); method.SetReturnType(resultType); return(method); }
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); }
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); } } }
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); }
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"); } } } }