/// <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 })); } }
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); }
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); }
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); }
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};")); }
/// <inheritdoc /> public void AttributeMethodProperty(PropertyBuilder propertyBuilder, IEndPointMethodConfigurationReadOnly methodConfiguration, RpcParameterInfo parameterInfoParameter) { }
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); }