Exemple #1
0
        /// <summary>
        /// Support version 0.0.6 before
        /// </summary>
        /// <param name="method"></param>
        /// <param name="parameter"></param>
        /// <param name="namespaceName"></param>
        /// <param name="codeBuilder"></param>
        /// <param name="bindServicesCode"></param>
        private void GenerateGrpcCallCodeForOldVersion(MethodInfo method, RpcParameterInfo parameter, string namespaceName,
                                                       string serviceName, CodeBuilder codeBuilder, ref StringBuilder bindServicesCode)
        {
            var serviceDefName = $"{namespaceName}.{serviceName}";
            var methodDefName  = method.Name.Replace("Async", "");
            var key            = $"{serviceDefName}.{methodDefName}";

            if (_oldVersionGrpcMethods.ContainsKey(key))
            {
                return;
            }
            bindServicesCode.AppendLine($@"
                .AddMethod(new Method<{parameter.ParameterType.Name}, {GrpcServiceBuilder.GetMethodReturn(method).Name}>(
                    MethodType.Unary,
                    ""{serviceDefName}"",
                    ""{methodDefName}"",
                    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", "")})");
            _oldVersionGrpcMethods.Add(key, key);
        }
 protected virtual void GenerateIntDefault(TypeBuilder typeBuilder,
                                           IEndPointMethodConfigurationReadOnly methodConfiguration, TypeCreationContext creationContext,
                                           ILGenerator ilGenerator, RpcParameterInfo rpcParameterInfo, FieldBuilder backingField)
 {
     ilGenerator.Emit(OpCodes.Ldarg_0);
     ilGenerator.EmitInt((int)rpcParameterInfo.DefaultValue);
     ilGenerator.Emit(OpCodes.Stfld, backingField);
 }
        /// <summary>
        /// Set parameter source based on type
        /// </summary>
        /// <param name="routeInformation"></param>
        /// <param name="parameterType"></param>
        /// <param name="rpcParameter"></param>
        /// <param name="parameterInfo"></param>
        protected virtual void SetParameterSource(IRpcRouteInformation routeInformation, Type parameterType,
                                                  RpcParameterInfo rpcParameter, ParameterInfo parameterInfo)
        {
            var attributes = parameterInfo.GetCustomAttributes <Attribute>().ToList();

            if (_exposeConfigurations.ResolveFromContainer(parameterType) ||
                attributes.Any(a => a is BindFromServicesAttribute))
            {
                rpcParameter.ParameterSource = EndPointMethodParameterSource.RequestServices;
            }
            else if (parameterType == typeof(RequestExecutionContext))
            {
                rpcParameter.ParameterSource = EndPointMethodParameterSource.RequestExecutionContext;
            }
            else if (parameterType == typeof(HttpContext))
            {
                rpcParameter.ParameterSource = EndPointMethodParameterSource.HttpContext;
            }
            else if (parameterType == typeof(HttpResponse))
            {
                rpcParameter.ParameterSource = EndPointMethodParameterSource.HttpResponse;
            }
            else if (parameterType == typeof(HttpRequest))
            {
                rpcParameter.ParameterSource = EndPointMethodParameterSource.HttpRequest;
            }
            else if (parameterType == typeof(CancellationToken))
            {
                rpcParameter.ParameterSource = EndPointMethodParameterSource.HttpCancellationToken;
            }
            else if (attributes.Any(a => a is BindNewDataAttribute) ||
                     _exposeConfigurations.NewDataTypeFunc(parameterType))
            {
                rpcParameter.ParameterSource = EndPointMethodParameterSource.NewData;
            }
            else
            {
                var matchingToken =
                    routeInformation.Tokens.FirstOrDefault(token => string.Compare(token.Name, rpcParameter.Name, StringComparison.CurrentCultureIgnoreCase) == 0);

                if (matchingToken != null)
                {
                    rpcParameter.ParameterSource = EndPointMethodParameterSource.PathParameter;

                    matchingToken.ParameterInfo = rpcParameter;
                }
                else if (routeInformation.HasBody)
                {
                    rpcParameter.ParameterSource = EndPointMethodParameterSource.PostParameter;
                }
                else
                {
                    rpcParameter.ParameterSource = EndPointMethodParameterSource.QueryStringParameter;
                }
            }
        }
        /// <inheritdoc />
        public void AttributeMethodProperty(PropertyBuilder propertyBuilder,
                                            IEndPointMethodConfigurationReadOnly methodConfiguration,
                                            RpcParameterInfo parameterInfoParameter)
        {
            if (!_useNameAsKey &&
                parameterInfoParameter.ParameterSource == EndPointMethodParameterSource.PostParameter)
            {
                var position = GetPosition(methodConfiguration, parameterInfoParameter);

                propertyBuilder.SetCustomAttribute(new CustomAttributeBuilder(_messagePackIntKeyAttrInfo, new object[] { position }));
            }
        }
Exemple #5
0
        private void GenerateProtoCode(MethodInfo method, RpcParameterInfo parameter, ref StringBuilder protoServiceCode, ref StringBuilder protoMessageCode)
        {
            var str = $"rpc {method.Name.Replace("Async", "")}({parameter.ParameterType.Name}) returns({GrpcServiceBuilder.GetMethodReturn(method).Name});";

            protoServiceCode.AppendLine();
            protoServiceCode.AppendLine(str);
            if (!_messages.Contains(parameter.ParameterType.Name))
            {
                protoMessageCode.AppendLine(GenerateProtoMessageCode(parameter.ParameterType));
                _messages.Add(parameter.ParameterType.Name);
            }
            if (_messages.Contains(GrpcServiceBuilder.GetMethodReturn(method).Name))
            {
                return;
            }
            protoMessageCode.AppendLine(GenerateProtoMessageCode(GrpcServiceBuilder.GetMethodReturn(method).ReturnType));
            _messages.Add(GrpcServiceBuilder.GetMethodReturn(method).Name);
        }
Exemple #6
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);
        }
        protected virtual void GenerateComplexDefault(TypeBuilder typeBuilder,
                                                      IEndPointMethodConfigurationReadOnly methodConfiguration,
                                                      TypeCreationContext creationContext,
                                                      ILGenerator ilGenerator,
                                                      RpcParameterInfo rpcParameterInfo,
                                                      FieldBuilder backingField)
        {
            var defaultFieldName = "_internal_default_" + rpcParameterInfo.Name;

            var staticField = typeBuilder.DefineField(defaultFieldName,
                                                      rpcParameterInfo.ParamType, FieldAttributes.Private | FieldAttributes.Static);

            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldsfld, staticField);
            ilGenerator.Emit(OpCodes.Stfld, backingField);

            creationContext.InitActions.Add(type =>
            {
                var internalField = type.GetTypeInfo().GetField(defaultFieldName, BindingFlags.Static | BindingFlags.NonPublic);

                internalField.SetValue(null, rpcParameterInfo.DefaultValue);
            });
        }
        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 int GetPosition(IEndPointMethodConfigurationReadOnly methodConfiguration, RpcParameterInfo parameterInfoParameter)
        {
            var position = 0;

            foreach (var currentParam in methodConfiguration.Parameters)
            {
                if (currentParam == parameterInfoParameter)
                {
                    break;
                }

                if (currentParam.ParameterSource == EndPointMethodParameterSource.PostParameter)
                {
                    position++;
                }
            }

            return(position);
        }
Exemple #10
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);
        }
Exemple #11
0
        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};"));
        }
Exemple #12
0
 /// <inheritdoc />
 public void AttributeMethodProperty(PropertyBuilder propertyBuilder, IEndPointMethodConfigurationReadOnly methodConfiguration,
                                     RpcParameterInfo parameterInfoParameter)
 {
 }
Exemple #13
0
        private List <RpcParameterInfo> GenerateMethodParameters(Type instanceType, MethodInfo methodInfo, RpcRouteInformation routeInformation)
        {
            var parameterList = new List <RpcParameterInfo>();
            var bodyParams    = 0;
            var lastPosition  = 0;

            foreach (var parameterInfo in methodInfo.GetParameters())
            {
                var rpcParam = new RpcParameterInfo
                {
                    Position        = parameterInfo.Position,
                    Name            = parameterInfo.Name,
                    HasDefaultValue = parameterInfo.HasDefaultValue,
                    DefaultValue    = parameterInfo.HasDefaultValue ? parameterInfo.DefaultValue : null,
                    ParamType       = parameterInfo.ParameterType
                };

                lastPosition = parameterInfo.Position;

                SetParameterSource(routeInformation, parameterInfo.ParameterType, rpcParam, parameterInfo);

                if (rpcParam.ParameterSource == EndPointMethodParameterSource.PostParameter)
                {
                    bodyParams++;
                }

                parameterList.Add(rpcParam);
            }

            if (instanceType != null)
            {
                foreach (var propertyInfo in instanceType.GetProperties())
                {
                    var rpcParam = ProcessProperty(propertyInfo);

                    if (rpcParam != null)
                    {
                        rpcParam.BindingType = EndPointBindingType.InstanceProperty;
                        rpcParam.Name        = propertyInfo.Name;
                        rpcParam.ParamType   = propertyInfo.PropertyType;

                        parameterList.Add(rpcParam);

                        rpcParam.Position = parameterList.Count - 1;
                    }
                }
            }

            foreach (var routeToken in routeInformation.Tokens)
            {
                if (routeToken.ParameterInfo == null)
                {
                    var rpcParam = new RpcParameterInfo
                    {
                        Name            = routeToken.Name,
                        HasDefaultValue = false,
                        DefaultValue    = null,
                        ParamType       = GetParameterTypeFromTokenType(routeToken.ParseType),
                        ParameterSource = EndPointMethodParameterSource.PathParameter,
                        BindingType     = EndPointBindingType.Other
                    };

                    parameterList.Add(rpcParam);

                    rpcParam.Position = parameterList.Count - 1;
                }
            }

            if (bodyParams == 1 &&
                _exposeConfigurations.SingleParameterPostFromBody)
            {
                var parameter = parameterList.First(rpc =>
                                                    rpc.ParameterSource == EndPointMethodParameterSource.PostParameter);

                if (!DefaultExposeDelegates.SimpleTypeWrapSelector(parameter.ParamType))
                {
                    parameter.ParameterSource = EndPointMethodParameterSource.PostBody;
                }
            }

            return(parameterList);
        }