From 8aa3263d219c155405cc384cde01c7ca0e9de1b7 Mon Sep 17 00:00:00 2001 From: jroger Date: Sun, 14 Apr 2024 06:58:15 +0800 Subject: [PATCH 1/5] feat: supported ServerStreaming --- README.md | 2 +- sample/ClientSample/Program.cs | 23 +++++++-- sample/InterfaceLib/IUserService.cs | 3 ++ .../Properties/launchSettings.json | 8 +-- sample/ServerSample/UserService.cs | 36 +++++++++++-- src/SimpleRpc.Client/DefaultRpcChannel.cs | 11 ++++ src/SimpleRpc.Client/IRpcChannel.cs | 4 ++ .../Internal/GrpcClientBase.cs | 11 +++- .../Internal/GrpcClientTypeBuilder.cs | 50 ++++++++++++++++--- src/SimpleRpc.Server/IRpcHostBuilder.cs | 9 ++++ .../Internal/GrpcHostBuilder.cs | 37 ++++++++++++-- .../Internal/GrpcHostBuilderExtensions.cs | 28 +++++++++-- .../Internal/MethodHandlerGenerator.cs | 14 ++++++ src/SimpleRpc.Server/RpcServiceBase.cs | 23 ++++++++- .../Description/RpcMethodDescription.cs | 10 ++-- .../ServiceAnnotations/RpcMethodAttribute.cs | 2 + 16 files changed, 237 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index b5ae998..54d6960 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,6 @@ Console.WriteLine($"Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto - [x] ClientStreaming supported. -- [ ] ServerStreaming supported. +- [x] ServerStreaming supported. - [ ] DuplexStreaming supported. diff --git a/sample/ClientSample/Program.cs b/sample/ClientSample/Program.cs index 71c604c..bd42799 100644 --- a/sample/ClientSample/Program.cs +++ b/sample/ClientSample/Program.cs @@ -39,12 +39,27 @@ async static Task Main(string[] args) var tokenSource = new CancellationTokenSource(1000 * 60 * 2); var rpcChannel = provider.GetService(); var call = rpcChannel.AsyncClientStreamingCall("greet.Greeter", "TestClientStreaming", tokenSource.Token); - await call.RequestStream.WriteAsync(new UserDto { Id = 1, Name = "abc1" }); - await call.RequestStream.WriteAsync(new UserDto { Id = 2, Name = "abc2" }); + await call.RequestStream.WriteAsync(new UserDto { Id = 1, Name = "client[ClientStreaming]1" }); + await call.RequestStream.WriteAsync(new UserDto { Id = 2, Name = "client[ClientStreaming]2" }); await call.RequestStream.CompleteAsync(); var userDto = await call; - Console.WriteLine($"Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); + Console.WriteLine($"ClientStreaming: Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); + } + else if (input.StartsWith(value: "ss:", StringComparison.OrdinalIgnoreCase)) + { + userRequest.Keyword = input; + var tokenSource = new CancellationTokenSource(1000 * 60 * 2); + var rpcChannel = provider.GetService(); + var call = rpcChannel.AsyncServerStreamingCall("greet.Greeter", "TestServerStreaming", new UserDto { Id = 1, Name = "client[ServerStreaming]1" }, tokenSource.Token); + await call.ResponseStream.MoveNext(tokenSource.Token); + var userDto = call.ResponseStream.Current; + Console.WriteLine($"ServerStreaming: Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); + + call = rpcChannel.AsyncServerStreamingCall("greet.Greeter", "TestServerStreaming", new UserDto { Id = 1, Name = "client[ServerStreaming]2" }, tokenSource.Token); + await call.ResponseStream.MoveNext(tokenSource.Token); + userDto = call.ResponseStream.Current; + Console.WriteLine($"ServerStreaming: Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); } else { @@ -53,7 +68,7 @@ async static Task Main(string[] args) var userService = provider.GetService(); var userDto = await userService.GetUserBy(userRequest, tokenSource.Token); - Console.WriteLine($"Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); + Console.WriteLine($"Unary: Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); } } diff --git a/sample/InterfaceLib/IUserService.cs b/sample/InterfaceLib/IUserService.cs index 6d9448a..15d2292 100644 --- a/sample/InterfaceLib/IUserService.cs +++ b/sample/InterfaceLib/IUserService.cs @@ -16,6 +16,9 @@ public interface IUserService : IRpcService [RpcMethod(MethodType = MethodType.ClientStreaming, RequestDataType = typeof(UserDto))] Task TestClientStreaming(CancellationToken token = default); + + [RpcMethod(MethodType = MethodType.ServerStreaming, RequestDataType = typeof(UserDto), ResponseDataType = typeof(UserDto))] + Task TestServerStreaming(UserDto request, CancellationToken token = default); } [ProtoContract] diff --git a/sample/ServerSample/Properties/launchSettings.json b/sample/ServerSample/Properties/launchSettings.json index b6d4ff7..9cbfbcb 100644 --- a/sample/ServerSample/Properties/launchSettings.json +++ b/sample/ServerSample/Properties/launchSettings.json @@ -1,7 +1,7 @@ { "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, + "windowsAuthentication": false, + "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:56092", "sslPort": 0 @@ -10,14 +10,14 @@ "profiles": { "IIS Express": { "commandName": "IISExpress", - "launchBrowser": true, + "launchBrowser": false, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "ServerSample": { "commandName": "Project", - "launchBrowser": true, + "launchBrowser": false, "applicationUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/sample/ServerSample/UserService.cs b/sample/ServerSample/UserService.cs index 06a81df..5300470 100644 --- a/sample/ServerSample/UserService.cs +++ b/sample/ServerSample/UserService.cs @@ -36,15 +36,45 @@ public async Task TestClientStreaming(CancellationToken token = default { var requestStream = this.GetAsyncStreamReader(); - while(await requestStream.MoveNext(token).ConfigureAwait(false)) + while (await requestStream.MoveNext(token).ConfigureAwait(false)) { - this._logger.LogInformation($"Receive client message:{JsonSerializer.Serialize(requestStream.Current)}"); + this._logger.LogInformation($"Receive client client stream message:{JsonSerializer.Serialize(requestStream.Current)}"); } - return new UserDto { + return new UserDto + { Id = (int)DateTime.Now.Ticks / 10000, Name = Guid.NewGuid().ToString("D"), CreateDate = DateTime.Now }; } + + public async Task TestServerStreaming(UserDto request, CancellationToken token = default) + { + this._logger.LogInformation($"Receive client server streaming message:{JsonSerializer.Serialize(request)}"); + + var responseStream = this.GetServerStreamWriter(); + + await responseStream.WriteAsync( + new UserDto + { + Id = (int)DateTime.Now.Ticks / 10000, + Name = Guid.NewGuid().ToString("D"), + CreateDate = DateTime.Now + }, + token + ); + + await Task.Delay(1000 * 2, token); + + await responseStream.WriteAsync( + new UserDto + { + Id = (int)DateTime.Now.Ticks / 10000, + Name = Guid.NewGuid().ToString("D"), + CreateDate = DateTime.Now + }, + token + ); + } } diff --git a/src/SimpleRpc.Client/DefaultRpcChannel.cs b/src/SimpleRpc.Client/DefaultRpcChannel.cs index 9ce0905..44c65f2 100644 --- a/src/SimpleRpc.Client/DefaultRpcChannel.cs +++ b/src/SimpleRpc.Client/DefaultRpcChannel.cs @@ -50,6 +50,17 @@ public AsyncClientStreamingCall AsyncClientStreamingCall AsyncServerStreamingCall(string serviceName, string methodName, TRequest request, CancellationToken token) + where TRequest : class + where TResponse : class + { + var callOptions = new CallOptions(cancellationToken: token).WithWaitForReady(); + var methodDefinition = this.GetMethodDefinition(MethodType.ServerStreaming, serviceName, methodName); + var result = this._invoker.AsyncServerStreamingCall(methodDefinition, this._host, callOptions, request); + + return result; + } + private Method GetMethodDefinition(MethodType methodType, string serviceName, string methodName) where TRequest : class where TResponse : class diff --git a/src/SimpleRpc.Client/IRpcChannel.cs b/src/SimpleRpc.Client/IRpcChannel.cs index b85949f..def7340 100644 --- a/src/SimpleRpc.Client/IRpcChannel.cs +++ b/src/SimpleRpc.Client/IRpcChannel.cs @@ -13,4 +13,8 @@ Task CallUnaryMethodAsync(TRequest request, stri AsyncClientStreamingCall AsyncClientStreamingCall(string serviceName, string methodName, CancellationToken token) where TRequest : class where TResponse : class; + + AsyncServerStreamingCall AsyncServerStreamingCall(string serviceName, string methodName, TRequest request, CancellationToken token) + where TRequest : class + where TResponse : class; } diff --git a/src/SimpleRpc.Client/Internal/GrpcClientBase.cs b/src/SimpleRpc.Client/Internal/GrpcClientBase.cs index 80b476b..0c1b983 100644 --- a/src/SimpleRpc.Client/Internal/GrpcClientBase.cs +++ b/src/SimpleRpc.Client/Internal/GrpcClientBase.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using Grpc.Core; using SimpleRpc.Shared; namespace SimpleRpc.Client.Internal; @@ -21,7 +22,6 @@ protected Task CallUnaryMethodAsync(TRequest req return this._rpcChannel.CallUnaryMethodAsync(request, serviceName, methodName, token); } - // TODO: change to ClientStreaming protected ClientStreaming AsyncClientStreamingCall(string serviceName, string methodName, CancellationToken token) where TRequest : class where TResponse : class @@ -32,4 +32,13 @@ protected ClientStreaming AsyncClientStreamingCall AsyncServerStreamingCall(string serviceName, string methodName, TRequest request, CancellationToken token) + where TRequest : class + where TResponse : class + { + var call = this._rpcChannel.AsyncServerStreamingCall(serviceName, methodName, request, token); + + return call; + } } diff --git a/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs b/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs index 297472d..2c6e238 100644 --- a/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs +++ b/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs @@ -14,6 +14,7 @@ internal class GrpcClientTypeBuilder private static readonly ConstructorInfo _ctorToCall = _clientBaseType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(IRpcChannel) }, null); private static readonly MethodInfo _unaryMethodToCall = _clientBaseType.GetMethod(nameof(IRpcChannel.CallUnaryMethodAsync), BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo _clientStreamingMethodToCall = _clientBaseType.GetMethod(nameof(IRpcChannel.AsyncClientStreamingCall), BindingFlags.Instance | BindingFlags.NonPublic); + private static readonly MethodInfo _serverStreamingMethodToCall = _clientBaseType.GetMethod(nameof(IRpcChannel.AsyncServerStreamingCall), BindingFlags.Instance | BindingFlags.NonPublic); public TypeInfo Create() where TService : class, IRpcService @@ -26,13 +27,13 @@ public TypeInfo Create() var typeBuilder = moduleBuilder.DefineType(serviceType.Name + "GrpcClientProxy", TypeAttributes.Public, _clientBaseType); typeBuilder.AddInterfaceImplementation(serviceType); - this.AddConstructor(typeBuilder); - this.AddMethods(typeBuilder, serviceType); + AddConstructor(typeBuilder); + AddMethods(typeBuilder, serviceType); return typeBuilder.CreateTypeInfo(); } - private void AddConstructor(TypeBuilder typeBuilder) + private static void AddConstructor(TypeBuilder typeBuilder) { var ctorBuilder = typeBuilder.DefineConstructor( MethodAttributes.Public, @@ -47,7 +48,7 @@ private void AddConstructor(TypeBuilder typeBuilder) il.Emit(OpCodes.Ret); } - private void AddMethods(TypeBuilder typeBuilder, Type serviceType) + private static void AddMethods(TypeBuilder typeBuilder, Type serviceType) { var serviceDescription = new RpcServiceDescription(serviceType); @@ -56,11 +57,15 @@ private void AddMethods(TypeBuilder typeBuilder, Type serviceType) switch (methodDescription.RpcMethodType) { case MethodType.Unary: - this.AddUnaryMethod(typeBuilder, serviceDescription, methodDescription); + AddUnaryMethod(typeBuilder, serviceDescription, methodDescription); break; case MethodType.ClientStreaming: - this.AddClientStreamingMethod(typeBuilder, serviceDescription, methodDescription); + AddClientStreamingMethod(typeBuilder, serviceDescription, methodDescription); + break; + + case MethodType.ServerStreaming: + AddServerStreamingMethod(typeBuilder, serviceDescription, methodDescription); break; default: @@ -69,7 +74,7 @@ private void AddMethods(TypeBuilder typeBuilder, Type serviceType) } } - private void AddUnaryMethod(TypeBuilder typeBuilder, RpcServiceDescription serviceDescription, RpcMethodDescription methodDescription) + private static void AddUnaryMethod(TypeBuilder typeBuilder, RpcServiceDescription serviceDescription, RpcMethodDescription methodDescription) { var args = methodDescription.RpcMethod.GetParameters(); var methodBuilder = typeBuilder.DefineMethod( @@ -98,7 +103,7 @@ private void AddUnaryMethod(TypeBuilder typeBuilder, RpcServiceDescription servi typeBuilder.DefineMethodOverride(methodBuilder, methodDescription.RpcMethod); } - private void AddClientStreamingMethod(TypeBuilder typeBuilder, RpcServiceDescription serviceDescription, RpcMethodDescription methodDescription) + private static void AddClientStreamingMethod(TypeBuilder typeBuilder, RpcServiceDescription serviceDescription, RpcMethodDescription methodDescription) { var args = methodDescription.RpcMethod.GetParameters(); var methodBuilder = typeBuilder.DefineMethod( @@ -125,4 +130,33 @@ private void AddClientStreamingMethod(TypeBuilder typeBuilder, RpcServiceDescrip typeBuilder.DefineMethodOverride(methodBuilder, methodDescription.RpcMethod); } + + private static void AddServerStreamingMethod(TypeBuilder typeBuilder, RpcServiceDescription serviceDescription, RpcMethodDescription methodDescription) + { + var args = methodDescription.RpcMethod.GetParameters(); + var methodBuilder = typeBuilder.DefineMethod( + methodDescription.RpcMethodName, + MethodAttributes.Public | MethodAttributes.Virtual, + methodDescription.RpcMethod.ReturnType, + (from arg in args select arg.ParameterType).ToArray() + ); + var il = methodBuilder.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldstr, serviceDescription.RpcServiceName); + il.Emit(OpCodes.Ldstr, methodDescription.RpcMethodName); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Ldarg_2); + + il.Emit( + OpCodes.Call, + _serverStreamingMethodToCall.MakeGenericMethod(new[] { + methodDescription.ResponseDataType, + methodDescription.ResponseDataType + }) + ); + + il.Emit(OpCodes.Ret); + + typeBuilder.DefineMethodOverride(methodBuilder, methodDescription.RpcMethod); + } } diff --git a/src/SimpleRpc.Server/IRpcHostBuilder.cs b/src/SimpleRpc.Server/IRpcHostBuilder.cs index a01cc80..031107a 100644 --- a/src/SimpleRpc.Server/IRpcHostBuilder.cs +++ b/src/SimpleRpc.Server/IRpcHostBuilder.cs @@ -45,6 +45,15 @@ string methodName where TRequest : class where TResponse : class; + IRpcHostBuilder AddServerStreamingMethod( + Func handler, + string serviceName, + string methodName + ) + where TService : class, IRpcService + where TRequest : class + where TResponse : class; + /// /// 创建 Rpc 宿主服务. /// diff --git a/src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs b/src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs index 4e0a65f..6e2a3d1 100644 --- a/src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs +++ b/src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs @@ -20,16 +20,16 @@ internal class GrpcHostBuilder : IRpcHostBuilder private readonly IServiceProvider _serviceProvider; private readonly ServerServiceDefinition.Builder _builder; private readonly ISerializer _serializer; - private readonly ILoggerFactory loggerFactory; private readonly RpcServerOptions _options; + private readonly ILoggerFactory _loggerFactory; public GrpcHostBuilder(IServiceProvider serviceProvider, ISerializer serializer, IOptions options, ILoggerFactory loggerFactory) { this._serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); this._builder = ServerServiceDefinition.CreateBuilder(); this._serializer = serializer; - this.loggerFactory = loggerFactory; this._options = options.Value; + this._loggerFactory = loggerFactory; } public IRpcHostBuilder AddUnaryMethod ( @@ -89,6 +89,37 @@ string methodName return this; } + public IRpcHostBuilder AddServerStreamingMethod( + Func handler, + string serviceName, + string methodName + ) + where TService : class, IRpcService + where TRequest : class + where TResponse : class + { + var method = MethodDefinitionGenerator.CreateMethodDefinition(MethodType.ServerStreaming, serviceName, methodName, this._serializer); + + this._builder.AddMethod(method, LocalServerStreamingServerMethod); + + Task LocalServerStreamingServerMethod(TRequest request, IServerStreamWriter responseStream, ServerCallContext context) + { + using (var scope = this._serviceProvider.CreateScope()) + { + var service = scope.ServiceProvider.GetServices().First(s => !s.GetType().Name.EndsWith("GrpcClientProxy", StringComparison.OrdinalIgnoreCase)); + if (service is RpcServiceBase baseService) + { + baseService.Context = context; + baseService.SetServerStreamWriter(responseStream); + } + + return handler(service, request, context.CancellationToken); + } + } + + return this; + } + public IRpcHost Build() { var healthService = new HealthServiceImpl(); @@ -103,6 +134,6 @@ public IRpcHost Build() } }; - return new GrpcHost(server, loggerFactory); + return new GrpcHost(server, _loggerFactory); } } diff --git a/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs b/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs index 411c5a2..7c4762a 100644 --- a/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs +++ b/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; +using System.Threading.Tasks; using Grpc.Core; using SimpleRpc.Shared; using SimpleRpc.Shared.Description; @@ -21,6 +22,10 @@ internal static class GrpcHostBuilderExtensions private static readonly MethodInfo _clientStreamingHandlerGenerator = typeof(MethodHandlerGenerator).GetMethod(nameof(MethodHandlerGenerator.GenerateClientStreamingMethodHandler)); private static readonly MethodInfo _addClientStreamingMethod = typeof(GrpcHostBuilder).GetMethod(nameof(GrpcHostBuilder.AddClientStreamingMethod), BindingFlags.Public | BindingFlags.Instance); + // ServerStreaming + private static readonly MethodInfo _serverStreamingHandlerGenerator = typeof(MethodHandlerGenerator).GetMethod(nameof(MethodHandlerGenerator.GenerateServerStreamingMethodHandler)); + private static readonly MethodInfo _addServerStreamingMethod = typeof(GrpcHostBuilder).GetMethod(nameof(GrpcHostBuilder.AddServerStreamingMethod), BindingFlags.Public | BindingFlags.Instance); + public static IRpcHostBuilder RegisterRpcService(this IRpcHostBuilder builder, List rpcServiceDescriptions) { if (rpcServiceDescriptions.Count == 0) @@ -33,26 +38,39 @@ public static IRpcHostBuilder RegisterRpcService(this IRpcHostBuilder builder, L foreach (var rpcMethodDescription in rpcServiceDescription.RpcMethods) { var requestType = rpcMethodDescription.RpcMethod.GetParameters()[0].ParameterType; - var responseType = rpcMethodDescription.RpcMethod.ReturnType.GenericTypeArguments[0]; switch (rpcMethodDescription.RpcMethodType) { case MethodType.Unary: - var unaryHandlerGenerator = _unaryHandlerGenerator.MakeGenericMethod(rpcServiceDescription.RpcServiceType, requestType, responseType); + var unaryResponseType = rpcMethodDescription.RpcMethod.ReturnType.GenericTypeArguments[0]; + var unaryHandlerGenerator = _unaryHandlerGenerator.MakeGenericMethod(rpcServiceDescription.RpcServiceType, requestType, unaryResponseType); var unaryHandler = unaryHandlerGenerator.Invoke(null, new[] { rpcMethodDescription.RpcMethod }); - var addUnaryMethod = _addUnaryMethod.MakeGenericMethod(rpcServiceDescription.RpcServiceType, requestType, responseType); + var addUnaryMethod = _addUnaryMethod.MakeGenericMethod(rpcServiceDescription.RpcServiceType, requestType, unaryResponseType); addUnaryMethod.Invoke(builder, new[] { unaryHandler, rpcServiceDescription.RpcServiceName, rpcMethodDescription.RpcMethodName }); break; case MethodType.ClientStreaming: + var clientStreamingResponseType = rpcMethodDescription.RpcMethod.ReturnType.GenericTypeArguments[0]; // Func> - var clientStreamingHandlerGenerator = _clientStreamingHandlerGenerator.MakeGenericMethod(rpcServiceDescription.RpcServiceType, responseType); + var clientStreamingHandlerGenerator = _clientStreamingHandlerGenerator.MakeGenericMethod(rpcServiceDescription.RpcServiceType, clientStreamingResponseType); var clientStreamingHandler = clientStreamingHandlerGenerator.Invoke(null, new[] { rpcMethodDescription.RpcMethod }); - var addClientStreamingMethod = _addClientStreamingMethod.MakeGenericMethod(rpcServiceDescription.RpcServiceType, rpcMethodDescription.RequestDataType, responseType); + var addClientStreamingMethod = _addClientStreamingMethod.MakeGenericMethod(rpcServiceDescription.RpcServiceType, rpcMethodDescription.RequestDataType, clientStreamingResponseType); addClientStreamingMethod.Invoke(builder, new[] { clientStreamingHandler, rpcServiceDescription.RpcServiceName, rpcMethodDescription.RpcMethodName }); break; + + case MethodType.ServerStreaming: + // Func + var serverStreamingHandlerGenerator = _serverStreamingHandlerGenerator.MakeGenericMethod(rpcServiceDescription.RpcServiceType, rpcMethodDescription.RequestDataType); + var serverStreamingHandler = serverStreamingHandlerGenerator.Invoke(null, new[] { rpcMethodDescription.RpcMethod }); + + var addServerStreamingMethod = _addServerStreamingMethod.MakeGenericMethod(rpcServiceDescription.RpcServiceType, rpcMethodDescription.RequestDataType, rpcMethodDescription.ResponseDataType); + addServerStreamingMethod.Invoke(builder, new[] { serverStreamingHandler, rpcServiceDescription.RpcServiceName, rpcMethodDescription.RpcMethodName }); + break; + + default: + throw new NotSupportedException($"unsupport gRPC MethodType: {rpcMethodDescription.RpcMethodType}"); } } } diff --git a/src/SimpleRpc.Server/Internal/MethodHandlerGenerator.cs b/src/SimpleRpc.Server/Internal/MethodHandlerGenerator.cs index d86a233..a7ee6c3 100644 --- a/src/SimpleRpc.Server/Internal/MethodHandlerGenerator.cs +++ b/src/SimpleRpc.Server/Internal/MethodHandlerGenerator.cs @@ -37,4 +37,18 @@ public static Func> GenerateClientS return func; } + + public static Func GenerateServerStreamingMethodHandler(MethodInfo method) + { + var serviceParameter = Expression.Parameter(typeof(TService)); + var requestParameter = Expression.Parameter(typeof(TRequest)); + var ctParameter = Expression.Parameter(typeof(CancellationToken)); + var invocation = Expression.Call(serviceParameter, method, new[] { requestParameter, ctParameter }); + var func = Expression.Lambda>( + invocation, false, new[] { serviceParameter, requestParameter, ctParameter } + ) + .Compile(); + + return func; + } } diff --git a/src/SimpleRpc.Server/RpcServiceBase.cs b/src/SimpleRpc.Server/RpcServiceBase.cs index 3509b30..eb8009c 100644 --- a/src/SimpleRpc.Server/RpcServiceBase.cs +++ b/src/SimpleRpc.Server/RpcServiceBase.cs @@ -1,4 +1,5 @@ -using Grpc.Core; +using System; +using Grpc.Core; using SimpleRpc.Shared; namespace SimpleRpc.Server; @@ -6,6 +7,7 @@ namespace SimpleRpc.Server; public abstract class RpcServiceBase : IRpcService { private object _requestStream; + private object _responseStream; public ServerCallContext Context { get; internal set; } @@ -14,5 +16,22 @@ internal void SetAsyncStreamReader(IAsyncStreamReader reques this._requestStream = requestStream; } - public IAsyncStreamReader GetAsyncStreamReader() => (IAsyncStreamReader)this._requestStream; + internal void SetServerStreamWriter(IServerStreamWriter responseStream) + { + this._responseStream = responseStream; + } + + public IAsyncStreamReader GetAsyncStreamReader() + { + ArgumentNullException.ThrowIfNull(nameof(this._requestStream)); + + return this._requestStream as IAsyncStreamReader; + } + + public IServerStreamWriter GetServerStreamWriter() + { + ArgumentNullException.ThrowIfNull(nameof(this._responseStream)); + + return this._responseStream as IServerStreamWriter; + } } diff --git a/src/SimpleRpc.Shared/Description/RpcMethodDescription.cs b/src/SimpleRpc.Shared/Description/RpcMethodDescription.cs index f4b287d..75e4041 100644 --- a/src/SimpleRpc.Shared/Description/RpcMethodDescription.cs +++ b/src/SimpleRpc.Shared/Description/RpcMethodDescription.cs @@ -10,11 +10,12 @@ public sealed class RpcMethodDescription { public RpcMethodDescription(MethodInfo methodInfo) { - var (rpcMethodName, methodType, requestDataType) = GetRpcMethodInfo(methodInfo); + var (rpcMethodName, methodType, requestDataType, responseDataType) = GetRpcMethodInfo(methodInfo); this.RpcMethod = methodInfo; this.RpcMethodName = rpcMethodName; this.RpcMethodType = methodType; this.RequestDataType = requestDataType; + this.ResponseDataType = responseDataType; this.CheckRpcMethodParameterType(methodInfo); } @@ -27,14 +28,17 @@ public RpcMethodDescription(MethodInfo methodInfo) public Type RequestDataType { get; } - private static (string rpcMethodName, MethodType methodType, Type requestDataType) GetRpcMethodInfo(MethodInfo methodInfo) + public Type ResponseDataType { get; } + + private static (string rpcMethodName, MethodType methodType, Type requestDataType, Type responseDataType) GetRpcMethodInfo(MethodInfo methodInfo) { var attr = methodInfo.GetCustomAttribute(typeof(RpcMethodAttribute), true) as RpcMethodAttribute; return ( string.IsNullOrWhiteSpace(attr.Name) ? methodInfo.Name : attr.Name, attr.MethodType, - attr.RequestDataType + attr.RequestDataType, + attr.ResponseDataType ); } diff --git a/src/SimpleRpc.Shared/ServiceAnnotations/RpcMethodAttribute.cs b/src/SimpleRpc.Shared/ServiceAnnotations/RpcMethodAttribute.cs index edae07e..df483f8 100644 --- a/src/SimpleRpc.Shared/ServiceAnnotations/RpcMethodAttribute.cs +++ b/src/SimpleRpc.Shared/ServiceAnnotations/RpcMethodAttribute.cs @@ -12,6 +12,8 @@ public class RpcMethodAttribute : Attribute public Type RequestDataType { get; set; } + public Type ResponseDataType { get; set; } + public RpcMethodAttribute(string name = "") { this.Name = name; From 65de4060d4368a224e371ca59e45f8f69084be23 Mon Sep 17 00:00:00 2001 From: JRoger Date: Sun, 14 Apr 2024 09:39:21 +0800 Subject: [PATCH 2/5] feat: add ServerStreaming support. --- README.md | 24 +++++++++++++++++-- sample/ClientSample/Program.cs | 8 +++---- sample/InterfaceLib/IUserService.cs | 4 ++-- sample/ServerSample/UserService.cs | 9 ++++--- src/Directory.Build.props | 2 +- .../Internal/GrpcClientTypeBuilder.cs | 3 +-- src/SimpleRpc.Client/RpcClientFactory.cs | 3 +-- .../Internal/GrpcHostBuilderExtensions.cs | 2 +- 8 files changed, 35 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 54d6960..d312cb1 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ var userDto = await userService.GetUserBy(userRequest, tokenSource.Token); #### ClientStreaming ```csharp -// gRPC client side +// gRPC Client side var tokenSource = new CancellationTokenSource(1000 * 60 * 2); var rpcChannel = provider.GetService(); var call = rpcChannel.AsyncClientStreamingCall("greet.Greeter", "TestClientStreaming", tokenSource.Token); @@ -46,8 +46,28 @@ var userDto = await call; Console.WriteLine($"Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); ``` +// gRPC Server side +- see `IUserService.cs` file line: 17-18 +- see `UserService.cs` file line: 35-50 + #### ServerStreaming -> not supported +```csharp +// gRPC Client side +var tokenSource = new CancellationTokenSource(1000 * 60 * 2); +var rpcChannel = provider.GetService(); +var call = rpcChannel.AsyncServerStreamingCall("greet.Greeter", "TestServerStreaming", new UserRequest { Id = 1, Keyword = $"client[ServerStreaming]1: {input}" }, tokenSource.Token); +await call.ResponseStream.MoveNext(tokenSource.Token).ConfigureAwait(false); +var userDto = call.ResponseStream.Current; +Console.WriteLine($"ServerStreaming: Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); + +await call.ResponseStream.MoveNext(tokenSource.Token).ConfigureAwait(false); +userDto = call.ResponseStream.Current; +Console.WriteLine($"ServerStreaming: Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); +``` + +// gRPC Server side +- see `IUserService.cs` file line: 20-21 +- see `UserService.cs` file line: 52-78 #### DuplexStreaming > not supported diff --git a/sample/ClientSample/Program.cs b/sample/ClientSample/Program.cs index bd42799..adee537 100644 --- a/sample/ClientSample/Program.cs +++ b/sample/ClientSample/Program.cs @@ -48,16 +48,14 @@ async static Task Main(string[] args) } else if (input.StartsWith(value: "ss:", StringComparison.OrdinalIgnoreCase)) { - userRequest.Keyword = input; var tokenSource = new CancellationTokenSource(1000 * 60 * 2); var rpcChannel = provider.GetService(); - var call = rpcChannel.AsyncServerStreamingCall("greet.Greeter", "TestServerStreaming", new UserDto { Id = 1, Name = "client[ServerStreaming]1" }, tokenSource.Token); - await call.ResponseStream.MoveNext(tokenSource.Token); + var call = rpcChannel.AsyncServerStreamingCall("greet.Greeter", "TestServerStreaming", new UserRequest { Id = 1, Keyword = $"client[ServerStreaming]1: {input}" }, tokenSource.Token); + await call.ResponseStream.MoveNext(tokenSource.Token).ConfigureAwait(false); var userDto = call.ResponseStream.Current; Console.WriteLine($"ServerStreaming: Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); - call = rpcChannel.AsyncServerStreamingCall("greet.Greeter", "TestServerStreaming", new UserDto { Id = 1, Name = "client[ServerStreaming]2" }, tokenSource.Token); - await call.ResponseStream.MoveNext(tokenSource.Token); + await call.ResponseStream.MoveNext(tokenSource.Token).ConfigureAwait(false); userDto = call.ResponseStream.Current; Console.WriteLine($"ServerStreaming: Id: {userDto.Id}, Name: {userDto.Name}, CreateDate: {userDto.CreateDate:yyyy-MM-dd HH:mm:ss fff}"); } diff --git a/sample/InterfaceLib/IUserService.cs b/sample/InterfaceLib/IUserService.cs index 15d2292..dd4367d 100644 --- a/sample/InterfaceLib/IUserService.cs +++ b/sample/InterfaceLib/IUserService.cs @@ -17,8 +17,8 @@ public interface IUserService : IRpcService [RpcMethod(MethodType = MethodType.ClientStreaming, RequestDataType = typeof(UserDto))] Task TestClientStreaming(CancellationToken token = default); - [RpcMethod(MethodType = MethodType.ServerStreaming, RequestDataType = typeof(UserDto), ResponseDataType = typeof(UserDto))] - Task TestServerStreaming(UserDto request, CancellationToken token = default); + [RpcMethod(MethodType = MethodType.ServerStreaming, RequestDataType = typeof(UserRequest), ResponseDataType = typeof(UserDto))] + Task TestServerStreaming(UserRequest request, CancellationToken token = default); } [ProtoContract] diff --git a/sample/ServerSample/UserService.cs b/sample/ServerSample/UserService.cs index 5300470..820e972 100644 --- a/sample/ServerSample/UserService.cs +++ b/sample/ServerSample/UserService.cs @@ -49,20 +49,20 @@ public async Task TestClientStreaming(CancellationToken token = default }; } - public async Task TestServerStreaming(UserDto request, CancellationToken token = default) + public async Task TestServerStreaming(UserRequest request, CancellationToken token = default) { this._logger.LogInformation($"Receive client server streaming message:{JsonSerializer.Serialize(request)}"); var responseStream = this.GetServerStreamWriter(); + // NOTE: do not use method signature: Task WriteAsync(T message, CancellationToken cancellationToken) await responseStream.WriteAsync( new UserDto { Id = (int)DateTime.Now.Ticks / 10000, Name = Guid.NewGuid().ToString("D"), CreateDate = DateTime.Now - }, - token + } ); await Task.Delay(1000 * 2, token); @@ -73,8 +73,7 @@ await responseStream.WriteAsync( Id = (int)DateTime.Now.Ticks / 10000, Name = Guid.NewGuid().ToString("D"), CreateDate = DateTime.Now - }, - token + } ); } } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 40c1d9f..7a10b63 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,7 +5,7 @@ https://github.com/netcore-jroger/SimpleRpc https://github.com/netcore-jroger/SimpleRpc gRPC - 0.5.1 + 0.6.1 JRoger © 2019-2024 \ No newline at end of file diff --git a/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs b/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs index 2c6e238..7b0fd02 100644 --- a/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs +++ b/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs @@ -16,8 +16,7 @@ internal class GrpcClientTypeBuilder private static readonly MethodInfo _clientStreamingMethodToCall = _clientBaseType.GetMethod(nameof(IRpcChannel.AsyncClientStreamingCall), BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo _serverStreamingMethodToCall = _clientBaseType.GetMethod(nameof(IRpcChannel.AsyncServerStreamingCall), BindingFlags.Instance | BindingFlags.NonPublic); - public TypeInfo Create() - where TService : class, IRpcService + public TypeInfo Create() where TService : class, IRpcService { var assemblyName = $"SimpleRpc.ClientProxy_{Guid.NewGuid():N}"; var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run); diff --git a/src/SimpleRpc.Client/RpcClientFactory.cs b/src/SimpleRpc.Client/RpcClientFactory.cs index 4ae0524..ed8a508 100644 --- a/src/SimpleRpc.Client/RpcClientFactory.cs +++ b/src/SimpleRpc.Client/RpcClientFactory.cs @@ -11,8 +11,7 @@ public static class RpcClientFactory private static readonly ConcurrentDictionary _proxyClientCache = new ConcurrentDictionary(); private static readonly GrpcClientTypeBuilder _builder = new GrpcClientTypeBuilder(); - public static TService Create(IRpcChannel rpcChannel) - where TService : class, IRpcService + public static TService Create(IRpcChannel rpcChannel) where TService : class, IRpcService { var serviceType = typeof(TService); if (!_proxyClientCache.ContainsKey(serviceType) || !_proxyClientCache.TryGetValue(serviceType, out var serviceInstanceTypeInfo)) diff --git a/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs b/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs index 7c4762a..e2062c7 100644 --- a/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs +++ b/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs @@ -61,7 +61,7 @@ public static IRpcHostBuilder RegisterRpcService(this IRpcHostBuilder builder, L break; case MethodType.ServerStreaming: - // Func + // Func var serverStreamingHandlerGenerator = _serverStreamingHandlerGenerator.MakeGenericMethod(rpcServiceDescription.RpcServiceType, rpcMethodDescription.RequestDataType); var serverStreamingHandler = serverStreamingHandlerGenerator.Invoke(null, new[] { rpcMethodDescription.RpcMethod }); From ea92fd7ea862a6d0df29b1d34676c60197c8a482 Mon Sep 17 00:00:00 2001 From: JRoger Date: Sun, 14 Apr 2024 09:56:09 +0800 Subject: [PATCH 3/5] chore: add .editorconfig code style config file --- .editorconfig | 284 ++++++++++++++++++++++++++++++++++++++++++++ azure-pipelines.yml | 34 ------ 2 files changed, 284 insertions(+), 34 deletions(-) create mode 100644 .editorconfig delete mode 100644 azure-pipelines.yml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7c74caa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,284 @@ +# top-most EditorConfig file +root = true + +[*] +indent_style = space +trim_trailing_whitespace = true +insert_final_newline = true + +indent_size = 4 +charset = utf-8 + +# CSharp and Visual Basic code style settings: +dotnet_style_qualification_for_field = true:suggestion +dotnet_style_qualification_for_property = true:suggestion +dotnet_style_qualification_for_method = true:suggestion +dotnet_style_qualification_for_event = true:suggestion + +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +dotnet_style_require_accessibility_modifiers = always:suggestion +dotnet_style_readonly_field = true:warning + +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent + +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion + +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent + +dotnet_code_quality_unused_parameters = all:suggestion + +[*.cs] +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:suggestion + +# new-line formatting settings +csharp_new_line_before_open_brace = local_functions, indexers, events, methods, properties, control_blocks, types +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_between_query_expression_clauses = true + +# indent formatting settings +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents_when_block = false + +# spacing formatting settings +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_parentheses = control_flow_statements +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_after_comma = true +csharp_space_before_comma = false +csharp_space_after_dot = false +csharp_space_before_dot = false +csharp_space_after_semicolon_in_for_statement = true +csharp_space_before_semicolon_in_for_statement = false +csharp_space_around_declaration_statements = false +csharp_space_before_open_square_brackets = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_square_brackets = false + +# wrap formatting settings +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +# CSharp code style settings: +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +csharp_style_expression_bodied_methods = true:suggestion +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = true:suggestion +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_indexers = true:suggestion +csharp_style_expression_bodied_accessors = true:suggestion +csharp_style_expression_bodied_lambdas = true:suggestion +csharp_style_expression_bodied_local_functions = true:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion + +csharp_style_inlined_variable_declaration = true:suggestion + +csharp_prefer_simple_default_expression = true:suggestion + +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = false:suggestion + +csharp_prefer_braces = true:suggestion + +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_unused_value_assignment_preference = discard_variable:suggestion + +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion + +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_prefer_static_local_function = true:suggestion +csharp_prefer_simple_using_statement = true:silent +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_prefer_top_level_statements = true:silent +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent +csharp_style_prefer_primary_constructors = true:suggestion +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_style_prefer_local_over_anonymous_function = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_prefer_readonly_struct = true:suggestion +csharp_style_prefer_readonly_struct_member = true:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent +csharp_style_prefer_pattern_matching = true:silent +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion + + +# Visual Basic code style settings: +[*.vb] +visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion +charset = utf-8 + +# XML project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 +charset = utf-8 + +# Shell script files +[*.sh] +indent_size = 2 +end_of_line = lf +charset = utf-8 + +# Powershell files +[*.ps1] +indent_size = 2 +charset = utf-8 + +[*.{cs,vb}] +file_header_template = Copyright (c) JRoger. All Rights Reserved. +dotnet_sort_system_directives_first = true + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Define the 'private_fields' symbol group: +dotnet_naming_symbols.private_fields.applicable_kinds = field +dotnet_naming_symbols.private_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_fields.required_modifiers = + +dotnet_naming_rule.private_fields.symbols = private_fields +dotnet_naming_rule.private_fields.style = underscored +dotnet_naming_rule.private_fields.severity = error + +# Define the 'private_readonly_fields' symbol group: +dotnet_naming_symbols.private_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.private_readonly_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_readonly_fields.required_modifiers = readonly + +dotnet_naming_rule.private_readonly_fields.symbols = private_readonly_fields +dotnet_naming_rule.private_readonly_fields.style = underscored +dotnet_naming_rule.private_readonly_fields.severity = error + +# Define the 'private_static_fields' symbol group +dotnet_naming_symbols.private_static_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_static_fields.required_modifiers = static + +dotnet_naming_rule.private_static_fields.symbols = private_static_fields +dotnet_naming_rule.private_static_fields.style = underscored +dotnet_naming_rule.private_static_fields.severity = error + +# Define the 'private_const_fields' naming rule + +dotnet_naming_symbols.private_const_fields.applicable_kinds = field +dotnet_naming_symbols.private_const_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_const_fields.required_modifiers = const + +dotnet_naming_rule.private_const_fields.symbols = private_const_fields +dotnet_naming_rule.private_const_fields.style = const_fields +dotnet_naming_rule.private_const_fields.severity = error + +# Naming styles + +# Define the 'underscored' naming style +dotnet_naming_style.underscored.capitalization = camel_case +dotnet_naming_style.underscored.required_prefix = _ + +# Define the 'const_fields' naming style +dotnet_naming_style.const_fields.capitalization = all_upper +dotnet_naming_style.const_fields.required_prefix = +dotnet_naming_style.const_fields.word_separator = _ + +# Define the 'Interface' naming style +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +end_of_line = crlf +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_allow_multiple_blank_lines_experimental = true:silent +dotnet_style_allow_statement_immediately_after_block_experimental = true:silent diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index cc829ca..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,34 +0,0 @@ -# ASP.NET Core (.NET Framework) -# Build and test ASP.NET Core projects targeting the full .NET Framework. -# Add steps that publish symbols, save build artifacts, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core - -trigger: -- master - -pool: - vmImage: 'windows-latest' - -variables: - solution: '**/*.sln' - buildPlatform: 'Any CPU' - buildConfiguration: 'Release' - -steps: -- task: NuGetToolInstaller@0 - -- task: NuGetCommand@2 - inputs: - restoreSolution: '$(solution)' - -- task: VSBuild@1 - inputs: - solution: '$(solution)' - msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"' - platform: '$(buildPlatform)' - configuration: '$(buildConfiguration)' - -- task: VSTest@2 - inputs: - platform: '$(buildPlatform)' - configuration: '$(buildConfiguration)' From 8c862072249c0b112b48ea9f9a0e4e5c9af71a2d Mon Sep 17 00:00:00 2001 From: JRoger Date: Sun, 14 Apr 2024 09:57:03 +0800 Subject: [PATCH 4/5] feat: logging request gRPC endpoints --- src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs b/src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs index 6e2a3d1..caf512d 100644 --- a/src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs +++ b/src/SimpleRpc.Server/Internal/GrpcHostBuilder.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -22,6 +24,7 @@ internal class GrpcHostBuilder : IRpcHostBuilder private readonly ISerializer _serializer; private readonly RpcServerOptions _options; private readonly ILoggerFactory _loggerFactory; + private readonly ILogger _logger; public GrpcHostBuilder(IServiceProvider serviceProvider, ISerializer serializer, IOptions options, ILoggerFactory loggerFactory) { @@ -30,6 +33,7 @@ public GrpcHostBuilder(IServiceProvider serviceProvider, ISerializer serializer, this._serializer = serializer; this._options = options.Value; this._loggerFactory = loggerFactory; + this._logger = loggerFactory.CreateLogger(); } public IRpcHostBuilder AddUnaryMethod ( @@ -51,6 +55,9 @@ string methodName { baseService.Context = context; } + + this._logger.LogInformation($"Request gRPC endpoint: {context.Method}"); + return handler(service, request, context.CancellationToken); } } @@ -81,6 +88,9 @@ string methodName baseService.Context = context; baseService.SetAsyncStreamReader(requestStream); } + + this._logger.LogInformation($"Request gRPC endpoint: {context.Method}"); + return handler(service, context.CancellationToken); } } @@ -113,6 +123,8 @@ Task LocalServerStreamingServerMethod(TRequest request, IServerStreamWriter Date: Sun, 14 Apr 2024 09:57:25 +0800 Subject: [PATCH 5/5] chore: code format, add file header. --- sample/ClientSample/Program.cs | 4 +++- sample/InterfaceLib/IUserService.cs | 4 +++- sample/ServerSample/Program.cs | 4 +++- sample/ServerSample/Startup.cs | 4 +++- sample/ServerSample/UserService.cs | 4 +++- src/SimpleRpc.Client/DefaultRpcChannel.cs | 2 ++ src/SimpleRpc.Client/IRpcChannel.cs | 2 ++ src/SimpleRpc.Client/IRpcServiceDiscovery.cs | 2 ++ src/SimpleRpc.Client/Internal/GrpcClientBase.cs | 4 +++- .../Internal/GrpcClientTypeBuilder.cs | 4 +++- src/SimpleRpc.Client/RpcClientFactory.cs | 4 +++- src/SimpleRpc.Client/RpcClientOptions.cs | 4 +++- src/SimpleRpc.Client/ServiceCollectionExtensions.cs | 4 +++- src/SimpleRpc.Server/IRpcHost.cs | 4 +++- src/SimpleRpc.Server/IRpcHostBuilder.cs | 12 ++++++++++++ src/SimpleRpc.Server/IRpcServiceRegister.cs | 2 ++ src/SimpleRpc.Server/IRpcServiceTypeFinder.cs | 4 +++- src/SimpleRpc.Server/Internal/GrpcHost.cs | 4 +++- .../Internal/GrpcHostBuilderExtensions.cs | 3 ++- src/SimpleRpc.Server/Internal/GrpcHostFactory.cs | 4 +++- .../Internal/MethodHandlerGenerator.cs | 4 +++- src/SimpleRpc.Server/RpcHostedService.cs | 4 +++- src/SimpleRpc.Server/RpcServerOptions.cs | 4 +++- src/SimpleRpc.Server/RpcServiceBase.cs | 4 +++- src/SimpleRpc.Server/ServiceCollectionExtensions.cs | 6 ++++-- src/SimpleRpc.Shared/ClientStreaming.cs | 4 +++- .../Description/RpcMethodDescription.cs | 4 +++- .../Description/RpcServiceDescription.cs | 4 +++- src/SimpleRpc.Shared/IRpcService.cs | 4 +++- .../Internal/MethodDefinitionGenerator.cs | 4 +++- src/SimpleRpc.Shared/RpcConfigInformation.cs | 4 +++- src/SimpleRpc.Shared/RpcDefineException.cs | 4 +++- src/SimpleRpc.Shared/Serializers/ISerializer.cs | 4 +++- .../Serializers/ProtoBufSerializer.cs | 4 +++- .../ServiceAnnotations/RpcMethodAttribute.cs | 4 +++- .../ServiceAnnotations/RpcServiceAttribute.cs | 4 +++- 36 files changed, 113 insertions(+), 32 deletions(-) diff --git a/sample/ClientSample/Program.cs b/sample/ClientSample/Program.cs index adee537..cc7b721 100644 --- a/sample/ClientSample/Program.cs +++ b/sample/ClientSample/Program.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; diff --git a/sample/InterfaceLib/IUserService.cs b/sample/InterfaceLib/IUserService.cs index dd4367d..79f3e35 100644 --- a/sample/InterfaceLib/IUserService.cs +++ b/sample/InterfaceLib/IUserService.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Threading; using System.Threading.Tasks; using Grpc.Core; diff --git a/sample/ServerSample/Program.cs b/sample/ServerSample/Program.cs index d270ceb..305b5b2 100644 --- a/sample/ServerSample/Program.cs +++ b/sample/ServerSample/Program.cs @@ -1,4 +1,6 @@ -using Microsoft.AspNetCore; +// Copyright (c) JRoger. All Rights Reserved. + +using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; namespace ServerSample; diff --git a/sample/ServerSample/Startup.cs b/sample/ServerSample/Startup.cs index 526d0ce..e4d4e3c 100644 --- a/sample/ServerSample/Startup.cs +++ b/sample/ServerSample/Startup.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Collections.Generic; using System.Text; using Microsoft.AspNetCore.Builder; diff --git a/sample/ServerSample/UserService.cs b/sample/ServerSample/UserService.cs index 820e972..74ba438 100644 --- a/sample/ServerSample/UserService.cs +++ b/sample/ServerSample/UserService.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Text.Json; using System.Text.Encodings.Web; using System.Text.Unicode; diff --git a/src/SimpleRpc.Client/DefaultRpcChannel.cs b/src/SimpleRpc.Client/DefaultRpcChannel.cs index 44c65f2..a25f49c 100644 --- a/src/SimpleRpc.Client/DefaultRpcChannel.cs +++ b/src/SimpleRpc.Client/DefaultRpcChannel.cs @@ -1,3 +1,5 @@ +// Copyright (c) JRoger. All Rights Reserved. + using System; using System.Threading; using System.Threading.Tasks; diff --git a/src/SimpleRpc.Client/IRpcChannel.cs b/src/SimpleRpc.Client/IRpcChannel.cs index def7340..6969ffe 100644 --- a/src/SimpleRpc.Client/IRpcChannel.cs +++ b/src/SimpleRpc.Client/IRpcChannel.cs @@ -1,3 +1,5 @@ +// Copyright (c) JRoger. All Rights Reserved. + using System.Threading; using System.Threading.Tasks; using Grpc.Core; diff --git a/src/SimpleRpc.Client/IRpcServiceDiscovery.cs b/src/SimpleRpc.Client/IRpcServiceDiscovery.cs index b6c8fa4..85027da 100644 --- a/src/SimpleRpc.Client/IRpcServiceDiscovery.cs +++ b/src/SimpleRpc.Client/IRpcServiceDiscovery.cs @@ -1,3 +1,5 @@ +// Copyright (c) JRoger. All Rights Reserved. + using System.Threading.Tasks; using Microsoft.Extensions.Options; diff --git a/src/SimpleRpc.Client/Internal/GrpcClientBase.cs b/src/SimpleRpc.Client/Internal/GrpcClientBase.cs index 0c1b983..a672888 100644 --- a/src/SimpleRpc.Client/Internal/GrpcClientBase.cs +++ b/src/SimpleRpc.Client/Internal/GrpcClientBase.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Threading; using System.Threading.Tasks; using Grpc.Core; diff --git a/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs b/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs index 7b0fd02..ea2d1a7 100644 --- a/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs +++ b/src/SimpleRpc.Client/Internal/GrpcClientTypeBuilder.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Linq; using System.Reflection; using System.Reflection.Emit; diff --git a/src/SimpleRpc.Client/RpcClientFactory.cs b/src/SimpleRpc.Client/RpcClientFactory.cs index ed8a508..433466f 100644 --- a/src/SimpleRpc.Client/RpcClientFactory.cs +++ b/src/SimpleRpc.Client/RpcClientFactory.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Collections.Concurrent; using System.Reflection; using SimpleRpc.Client.Internal; diff --git a/src/SimpleRpc.Client/RpcClientOptions.cs b/src/SimpleRpc.Client/RpcClientOptions.cs index dd23f41..6d12250 100644 --- a/src/SimpleRpc.Client/RpcClientOptions.cs +++ b/src/SimpleRpc.Client/RpcClientOptions.cs @@ -1,4 +1,6 @@ -namespace SimpleRpc.Client; +// Copyright (c) JRoger. All Rights Reserved. + +namespace SimpleRpc.Client; public class RpcClientOptions { diff --git a/src/SimpleRpc.Client/ServiceCollectionExtensions.cs b/src/SimpleRpc.Client/ServiceCollectionExtensions.cs index 2458c36..a264baf 100644 --- a/src/SimpleRpc.Client/ServiceCollectionExtensions.cs +++ b/src/SimpleRpc.Client/ServiceCollectionExtensions.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.Configuration; +// Copyright (c) JRoger. All Rights Reserved. + +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using SimpleRpc.Shared.Serializers; diff --git a/src/SimpleRpc.Server/IRpcHost.cs b/src/SimpleRpc.Server/IRpcHost.cs index 595c544..48bcc28 100644 --- a/src/SimpleRpc.Server/IRpcHost.cs +++ b/src/SimpleRpc.Server/IRpcHost.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +// Copyright (c) JRoger. All Rights Reserved. + +using System.Threading.Tasks; namespace SimpleRpc.Server; diff --git a/src/SimpleRpc.Server/IRpcHostBuilder.cs b/src/SimpleRpc.Server/IRpcHostBuilder.cs index 031107a..1cd6853 100644 --- a/src/SimpleRpc.Server/IRpcHostBuilder.cs +++ b/src/SimpleRpc.Server/IRpcHostBuilder.cs @@ -1,3 +1,5 @@ +// Copyright (c) JRoger. All Rights Reserved. + using System; using System.Threading; using System.Threading.Tasks; @@ -45,6 +47,16 @@ string methodName where TRequest : class where TResponse : class; + /// + /// 添加 ServerStreamingMethod RPC 方法 + /// + /// + /// + /// + /// + /// + /// + /// IRpcHostBuilder AddServerStreamingMethod( Func handler, string serviceName, diff --git a/src/SimpleRpc.Server/IRpcServiceRegister.cs b/src/SimpleRpc.Server/IRpcServiceRegister.cs index 1918d67..4c734ad 100644 --- a/src/SimpleRpc.Server/IRpcServiceRegister.cs +++ b/src/SimpleRpc.Server/IRpcServiceRegister.cs @@ -1,3 +1,5 @@ +// Copyright (c) JRoger. All Rights Reserved. + using System; using System.Net.Http; using System.Text; diff --git a/src/SimpleRpc.Server/IRpcServiceTypeFinder.cs b/src/SimpleRpc.Server/IRpcServiceTypeFinder.cs index 92e0066..99c964b 100644 --- a/src/SimpleRpc.Server/IRpcServiceTypeFinder.cs +++ b/src/SimpleRpc.Server/IRpcServiceTypeFinder.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; diff --git a/src/SimpleRpc.Server/Internal/GrpcHost.cs b/src/SimpleRpc.Server/Internal/GrpcHost.cs index b2033ba..2cd3260 100644 --- a/src/SimpleRpc.Server/Internal/GrpcHost.cs +++ b/src/SimpleRpc.Server/Internal/GrpcHost.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Collections; using System.Reflection; using System.Text; diff --git a/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs b/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs index e2062c7..e66e761 100644 --- a/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs +++ b/src/SimpleRpc.Server/Internal/GrpcHostBuilderExtensions.cs @@ -1,10 +1,11 @@ +// Copyright (c) JRoger. All Rights Reserved. + using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; -using System.Threading.Tasks; using Grpc.Core; using SimpleRpc.Shared; using SimpleRpc.Shared.Description; diff --git a/src/SimpleRpc.Server/Internal/GrpcHostFactory.cs b/src/SimpleRpc.Server/Internal/GrpcHostFactory.cs index 4e5a8e1..eb72d73 100644 --- a/src/SimpleRpc.Server/Internal/GrpcHostFactory.cs +++ b/src/SimpleRpc.Server/Internal/GrpcHostFactory.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Linq; using Microsoft.Extensions.DependencyInjection; diff --git a/src/SimpleRpc.Server/Internal/MethodHandlerGenerator.cs b/src/SimpleRpc.Server/Internal/MethodHandlerGenerator.cs index a7ee6c3..e851f57 100644 --- a/src/SimpleRpc.Server/Internal/MethodHandlerGenerator.cs +++ b/src/SimpleRpc.Server/Internal/MethodHandlerGenerator.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Linq.Expressions; using System.Reflection; using System.Threading; diff --git a/src/SimpleRpc.Server/RpcHostedService.cs b/src/SimpleRpc.Server/RpcHostedService.cs index 994b3f0..b6bf37f 100644 --- a/src/SimpleRpc.Server/RpcHostedService.cs +++ b/src/SimpleRpc.Server/RpcHostedService.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; diff --git a/src/SimpleRpc.Server/RpcServerOptions.cs b/src/SimpleRpc.Server/RpcServerOptions.cs index ee3c016..4ad3673 100644 --- a/src/SimpleRpc.Server/RpcServerOptions.cs +++ b/src/SimpleRpc.Server/RpcServerOptions.cs @@ -1,4 +1,6 @@ -namespace SimpleRpc.Server; +// Copyright (c) JRoger. All Rights Reserved. + +namespace SimpleRpc.Server; public class RpcServerOptions { diff --git a/src/SimpleRpc.Server/RpcServiceBase.cs b/src/SimpleRpc.Server/RpcServiceBase.cs index eb8009c..aa8a156 100644 --- a/src/SimpleRpc.Server/RpcServiceBase.cs +++ b/src/SimpleRpc.Server/RpcServiceBase.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using Grpc.Core; using SimpleRpc.Shared; diff --git a/src/SimpleRpc.Server/ServiceCollectionExtensions.cs b/src/SimpleRpc.Server/ServiceCollectionExtensions.cs index d233ad1..08b290a 100644 --- a/src/SimpleRpc.Server/ServiceCollectionExtensions.cs +++ b/src/SimpleRpc.Server/ServiceCollectionExtensions.cs @@ -1,11 +1,13 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using SimpleRpc.Shared.Serializers; using SimpleRpc.Server.Internal; +using SimpleRpc.Shared.Serializers; namespace SimpleRpc.Server; diff --git a/src/SimpleRpc.Shared/ClientStreaming.cs b/src/SimpleRpc.Shared/ClientStreaming.cs index 226a70b..2b045a4 100644 --- a/src/SimpleRpc.Shared/ClientStreaming.cs +++ b/src/SimpleRpc.Shared/ClientStreaming.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Grpc.Core; diff --git a/src/SimpleRpc.Shared/Description/RpcMethodDescription.cs b/src/SimpleRpc.Shared/Description/RpcMethodDescription.cs index 75e4041..1a1341c 100644 --- a/src/SimpleRpc.Shared/Description/RpcMethodDescription.cs +++ b/src/SimpleRpc.Shared/Description/RpcMethodDescription.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Reflection; using System.Threading; using Grpc.Core; diff --git a/src/SimpleRpc.Shared/Description/RpcServiceDescription.cs b/src/SimpleRpc.Shared/Description/RpcServiceDescription.cs index 564d4f2..0e298d2 100644 --- a/src/SimpleRpc.Shared/Description/RpcServiceDescription.cs +++ b/src/SimpleRpc.Shared/Description/RpcServiceDescription.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; diff --git a/src/SimpleRpc.Shared/IRpcService.cs b/src/SimpleRpc.Shared/IRpcService.cs index fdfac6c..dd744d8 100644 --- a/src/SimpleRpc.Shared/IRpcService.cs +++ b/src/SimpleRpc.Shared/IRpcService.cs @@ -1,4 +1,6 @@ -namespace SimpleRpc.Shared +// Copyright (c) JRoger. All Rights Reserved. + +namespace SimpleRpc.Shared { /// /// 一个空接口,用于标记一个 RPC 服务。 diff --git a/src/SimpleRpc.Shared/Internal/MethodDefinitionGenerator.cs b/src/SimpleRpc.Shared/Internal/MethodDefinitionGenerator.cs index 741efa8..1bcb29a 100644 --- a/src/SimpleRpc.Shared/Internal/MethodDefinitionGenerator.cs +++ b/src/SimpleRpc.Shared/Internal/MethodDefinitionGenerator.cs @@ -1,4 +1,6 @@ -using Grpc.Core; +// Copyright (c) JRoger. All Rights Reserved. + +using Grpc.Core; using SimpleRpc.Shared.Serializers; using System.Runtime.CompilerServices; diff --git a/src/SimpleRpc.Shared/RpcConfigInformation.cs b/src/SimpleRpc.Shared/RpcConfigInformation.cs index d6d5913..59dbd20 100644 --- a/src/SimpleRpc.Shared/RpcConfigInformation.cs +++ b/src/SimpleRpc.Shared/RpcConfigInformation.cs @@ -1,4 +1,6 @@ -namespace SimpleRpc.Shared +// Copyright (c) JRoger. All Rights Reserved. + +namespace SimpleRpc.Shared { public static class RpcConfigInformation { diff --git a/src/SimpleRpc.Shared/RpcDefineException.cs b/src/SimpleRpc.Shared/RpcDefineException.cs index 0ce2b1d..21afa0f 100644 --- a/src/SimpleRpc.Shared/RpcDefineException.cs +++ b/src/SimpleRpc.Shared/RpcDefineException.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; namespace SimpleRpc.Shared { diff --git a/src/SimpleRpc.Shared/Serializers/ISerializer.cs b/src/SimpleRpc.Shared/Serializers/ISerializer.cs index e098aba..c1d667d 100644 --- a/src/SimpleRpc.Shared/Serializers/ISerializer.cs +++ b/src/SimpleRpc.Shared/Serializers/ISerializer.cs @@ -1,4 +1,6 @@ -namespace SimpleRpc.Shared.Serializers +// Copyright (c) JRoger. All Rights Reserved. + +namespace SimpleRpc.Shared.Serializers { public interface ISerializer { diff --git a/src/SimpleRpc.Shared/Serializers/ProtoBufSerializer.cs b/src/SimpleRpc.Shared/Serializers/ProtoBufSerializer.cs index 80d899f..cfb0e93 100644 --- a/src/SimpleRpc.Shared/Serializers/ProtoBufSerializer.cs +++ b/src/SimpleRpc.Shared/Serializers/ProtoBufSerializer.cs @@ -1,4 +1,6 @@ -using ProtoBuf; +// Copyright (c) JRoger. All Rights Reserved. + +using ProtoBuf; using System.IO; namespace SimpleRpc.Shared.Serializers diff --git a/src/SimpleRpc.Shared/ServiceAnnotations/RpcMethodAttribute.cs b/src/SimpleRpc.Shared/ServiceAnnotations/RpcMethodAttribute.cs index df483f8..e09a2b1 100644 --- a/src/SimpleRpc.Shared/ServiceAnnotations/RpcMethodAttribute.cs +++ b/src/SimpleRpc.Shared/ServiceAnnotations/RpcMethodAttribute.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; using Grpc.Core; namespace SimpleRpc.Shared.ServiceAnnotations diff --git a/src/SimpleRpc.Shared/ServiceAnnotations/RpcServiceAttribute.cs b/src/SimpleRpc.Shared/ServiceAnnotations/RpcServiceAttribute.cs index e78a9e3..4ae0d22 100644 --- a/src/SimpleRpc.Shared/ServiceAnnotations/RpcServiceAttribute.cs +++ b/src/SimpleRpc.Shared/ServiceAnnotations/RpcServiceAttribute.cs @@ -1,4 +1,6 @@ -using System; +// Copyright (c) JRoger. All Rights Reserved. + +using System; namespace SimpleRpc.Shared.ServiceAnnotations {