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); }
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 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 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 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 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 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); }
private (String MethodType, string RequestType, string ResponseType) getCallInfo(CallType callType, MethodDescripter method) { switch (callType) { case CallType.Rpc: return("MethodType.Unary", method.Parameters[0].Type, method.ReturnTypeStr); case CallType.ClientStreamRpc: return("MethodType.ClientStreaming", method.Parameters[0].Type, method.ReturnTypeStr); case CallType.ServerStreamRpc: return("MethodType.ServerStreaming", method.Parameters[0].Type, method.Parameters[1].Type); case CallType.DuplexStreamRpc: return("MethodType.DuplexStreaming", method.Parameters[0].Type, method.Parameters[1].Type); default: throw new InvalidCastException("Invalid CallType"); } }
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); } } }