/// <summary> /// DuplexStreaming メソッドを生成します。 /// </summary> /// <typeparam name="TRequest">リクエストの型</typeparam> /// <typeparam name="TResponse">レスポンスの型</typeparam> /// <param name="builderContext">コンテキスト</param> /// <returns>メソッド</returns> private DuplexStreamingServerMethod <TRequest, TResponse> CreateDuplexStreamingServerMethod <TRequest, TResponse>(MethodBuildContext builderContext) where TRequest : class where TResponse : class { DuplexStreamingServerMethod <TRequest, TResponse> method = builderContext.MethodImpl.CreateDelegate(typeof(DuplexStreamingServerMethod <TRequest, TResponse>), builderContext.ServiceInstance) as DuplexStreamingServerMethod <TRequest, TResponse>; GrpcServerPerformanceListener performanceListener = builderContext.NeedNotifyPerformanceLog ? builderContext.Settings.PerformanceListener : null; return(async delegate(IAsyncStreamReader <TRequest> requestStream, IServerStreamWriter <TResponse> responseStream, ServerCallContext context) { try { await OnExecutingServiceMethodAsync(context, builderContext.InvokingInterceptors, performanceListener).ConfigureAwait(false); if (performanceListener != null) { performanceListener.NotifyMethodCalling(context); } Stopwatch watch = Stopwatch.StartNew(); double elapsd; try { await method( new RequestStreamReader <TRequest>(requestStream, context, performanceListener) , new ResponseStreamWriter <TResponse>(responseStream, context, performanceListener) , context ).ConfigureAwait(false); } catch (Exception ex) { throw new GrpcServerMethodException(string.Format(Properties.MessageResources.ServerMethodFailed, context.Method) + ex.Message, ex, context); } finally { elapsd = GrpcPerformanceListener.GetMilliseconds(watch); if (performanceListener != null) { performanceListener.NotifyMethodCalled(context, elapsd); } } await OnExecutedServiceMethodAsync(context, builderContext.InvokedInterceptors, performanceListener).ConfigureAwait(false); } catch (Exception ex) { Exception wrapped; if (HandleException(context, builderContext.ExceptionHandlers, performanceListener, ex, out wrapped)) { GrpcExceptionListener.NotifyCatchServerException(context, wrapped); throw wrapped; } else { GrpcExceptionListener.NotifyCatchServerException(context, ex); throw; } } }); }
/// <summary> /// サービスメソッド定義を生成します。 /// </summary> /// <typeparam name="TRequest">リクエストの型</typeparam> /// <typeparam name="TResponse">レスポンスの型</typeparam> /// <param name="context">コンテキスト</param> /// <returns>サービスメソッド定義></returns> private Method <TRequest, TResponse> CreateServiceMethodFieldGeneric <TRequest, TResponse>(MethodBuildContext context) { string serviceName = context.GetServiceName(); string methodName = context.GetServiceMethodName(); GrpcServerPerformanceListener performanceListener = context.NeedNotifyPerformanceLog ? context.Settings.PerformanceListener : null; Marshaller <TRequest> request = CreateMethodMarshaller <TRequest>(serviceName, methodName, performanceListener, context.Settings); Marshaller <TResponse> response = CreateMethodMarshaller <TResponse>(serviceName, methodName, performanceListener, context.Settings); return(new Method <TRequest, TResponse>(context.MethodType, serviceName, methodName, request, response)); }
/// <summary> /// 例外を処理します。 /// </summary> /// <param name="context">コンテキスト</param> /// <param name="exceptionHandlers">例外ハンドラ</param> /// <param name="performanceListener">パフォーマンスリスナー</param> /// <param name="original">発生した例外</param> /// <param name="alternate">代わりにスローする例外</param> /// <returns>例外がラップされた場合、true を返します。</returns> private bool HandleException(ServerCallContext context, IEnumerable <IGrpcServerMethodExceptionHandler> exceptionHandlers, GrpcServerPerformanceListener performanceListener, Exception original, out Exception alternate) { Exception alt = null; if (exceptionHandlers != null) { foreach (IGrpcServerMethodExceptionHandler handler in exceptionHandlers) { if (handler == null) { continue; } Stopwatch watch = Stopwatch.StartNew(); try { if (handler.RelpaceException(context, original, out alt)) { break; } } catch (Exception ex) { throw new GrpcServerMethodException(string.Format(Properties.MessageResources.ServerMethodInterceptorFailed + ex.Message, context.Method, handler.Name), ex, context, handler); } finally { if (performanceListener != null) { performanceListener.NotifyMethodIntercepted(context, handler, GrpcPerformanceListener.GetMilliseconds(watch)); } } } } if (alt == null) { alt = original; } RpcException rpc = alt as RpcException; if (rpc == null) { alternate = CreateRpcException(context, alt); } else { alternate = rpc; } return(!object.Equals(original, alternate)); }
/// <summary> /// サービスメソッドが呼び出されたときの処理を行います。 /// </summary> /// <param name="context">コンテキスト</param> /// <param name="interceptors">割込処理</param> /// <param name="performanceListener">パフォーマンスリスナー</param> /// <returns></returns> private async Task OnExecutedServiceMethodAsync(ServerCallContext context, IEnumerable <IGrpcServerMethodInvokedInterceptor> interceptors, GrpcServerPerformanceListener performanceListener) { if (interceptors != null) { foreach (IGrpcServerMethodInvokedInterceptor interceptor in interceptors) { if (interceptor == null) { continue; } Stopwatch watch = Stopwatch.StartNew(); try { await interceptor.OnInvokedAsync(context).ConfigureAwait(false); } catch (Exception ex) { throw new GrpcServerMethodException(string.Format(Properties.MessageResources.ServerMethodInterceptorFailed + ex.Message, context.Method, interceptor.Name), ex, context, interceptor); } finally { if (performanceListener != null) { performanceListener.NotifyMethodIntercepted(context, interceptor, GrpcPerformanceListener.GetMilliseconds(watch)); } } } } }
/// <summary> /// 指定されたメソッドに対するマーシャラーを生成します。 /// </summary> /// <typeparam name="T">オブジェクトの型</typeparam> /// <param name="serviceName">サービス名</param> /// <param name="methodName">メソッド名</param> /// <param name="performanceListener">パフォーマンスリスナー</param> /// <param name="settings">動作設定</param> /// <returns>マーシャラ</returns> private Marshaller <T> CreateMethodMarshaller <T>(string serviceName, string methodName, GrpcServerPerformanceListener performanceListener, GrpcServiceBuilderSettings settings) { Marshaller <T> marshaller = settings.GetMarshallerFactoryOrDefault().GetMarshaller <T>(); if (performanceListener == null) { return(marshaller); } string typeName = typeof(T).Name; return(new Marshaller <T>( delegate(T arg) { try { Stopwatch watch = Stopwatch.StartNew(); byte[] data = marshaller.Serializer(arg); performanceListener.NotifySerialized(serviceName, methodName, typeName, GrpcPerformanceListener.GetMilliseconds(watch), data == null ? 0 : data.Length); return data; } catch (Exception ex) { GrpcExceptionListener.NotifyCatchSerializerException(serviceName, methodName, typeof(T), ex); throw new GrpcSerializerException(ex.Message, ex, serviceName, methodName, typeName); } } , delegate(byte[] data) { try { Stopwatch watch = Stopwatch.StartNew(); T arg = marshaller.Deserializer(data); performanceListener.NotifyDeserialized(serviceName, methodName, typeName, GrpcPerformanceListener.GetMilliseconds(watch), data == null ? 0 : data.Length); return arg; } catch (Exception ex) { GrpcExceptionListener.NotifyCatchSerializerException(serviceName, methodName, typeof(T), ex); throw new GrpcSerializerException(ex.Message, ex, serviceName, methodName, typeName); } } )); }