示例#1
0
        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);
        }
示例#3
0
        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());
        }
示例#5
0
        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);
        }
示例#6
0
        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");
            }
        }
示例#10
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);
                }
            }
        }