/// <summary> /// 指定された例外を処理し、実行結果を返します。 /// </summary> /// <typeparam name="TRequest">リクエストの型</typeparam> /// <typeparam name="TResponse">レスポンスの型</typeparam> /// <typeparam name="TResult">実行結果の型</typeparam> /// <param name="call">呼び出しオブジェクト</param> /// <param name="ex">例外</param> /// <returns>実行結果</returns> private static GrpcResult <IList <TResult> > HandleResponseListException <TRequest, TResponse, TResult>(AsyncDuplexStreamingCall <TRequest, TResponse> call, Exception ex) { Exception actual = GrpcExceptionUtility.GetActualException(ex); GrpcCallState state; if (GrpcCallInvokerContext.TryGetState(call, out state)) { GrpcExceptionListener.NotifyCatchClientException(state.Method, state.Host, state.Options, actual); } return(GrpcResult.Create <IList <TResult> >(actual)); }
/// <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); } } )); }
/// <summary> /// Unary メソッドを非同期で呼び出します。 /// </summary> /// <typeparam name="TRequest">リクエストの型</typeparam> /// <typeparam name="TResponse">レスポンスの型</typeparam> /// <param name="method">メソッド</param> /// <param name="host">ホスト</param> /// <param name="options">オプション</param> /// <param name="request">リクエスト</param> /// <returns>呼び出しオブジェクト</returns> public override AsyncUnaryCall <TResponse> AsyncUnaryCall <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, TRequest request) { double elapsed = 0; try { method = GetCustomMethod <TRequest, TResponse>(method); OnInvokingMethod(method, host, options, request); Stopwatch watch = null; AsyncUnaryCall <TResponse> call; try { watch = Stopwatch.StartNew(); call = m_Invoker.AsyncUnaryCall(method, host, options, request); } finally { elapsed = GrpcPerformanceListener.GetMilliseconds(watch); } OnInvokedMethod(method, host, options, request, elapsed); // 待機されると dispose が呼ばれず、解放されずに残ってしまう // ストリーム操作もないため、監視しない // return GrcpCallInvokerContext.Regist<TRequest, TResponse>(call, method, host, options); return(call); } catch (Exception ex) { GrpcExceptionListener.NotifyCatchClientException(method, host, options, ex); Exception alternate; if (HandleException(method, host, options, ex, out alternate)) { throw alternate; } else { throw; } } }
/// <summary> /// 例外をキャッチしたときの処理を行います。 /// </summary> /// <typeparam name="TRequest">リクエストの型</typeparam> /// <typeparam name="TResponse">レスポンスの型</typeparam> /// <param name="method">メソッド</param> /// <param name="host">ホスト</param> /// <param name="options">オプション</param> /// <param name="original">キャッチした例外</param> /// <param name="alternate">代わりにスローさせる例外</param> /// <returns>処理された場合、true を返します。</returns> private bool HandleException <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, Exception original, out Exception alternate) { Exception alt = null; foreach (IGrpcClientMethodExceptionHandler interceptor in m_Settings.InvokingInterceptors) { if (interceptor == null) { continue; } Stopwatch watch = Stopwatch.StartNew(); try { bool wrapped = interceptor.ReplaceException(method, host, options, original, out alt); if (m_Settings.PerformanceListener != null) { m_Settings.PerformanceListener.NotifyMethodIntercepted(method, host, options, interceptor, GrpcPerformanceListener.GetMilliseconds(watch)); } if (wrapped) { break; } } catch (Exception ex) { GrpcExceptionListener.NotifyCatchClientException(method, host, options, ex); throw new GrpcClientMethodException(string.Format(Properties.MessageResources.ClientMethodInterceptorFailed + ex.Message, method.FullName, interceptor.Name), ex, method, host, options, interceptor); } } if (alt != null && !object.Equals(alt, original)) { alternate = alt; return(true); } else { alternate = null; return(false); } }
/// <summary> /// Unary メソッドを呼び出します。 /// </summary> /// <typeparam name="TRequest">リクエストの型</typeparam> /// <typeparam name="TResponse">レスポンスの型</typeparam> /// <param name="method">メソッド</param> /// <param name="host">ホスト</param> /// <param name="options">オプション</param> /// <param name="request">リクエスト</param> /// <returns>レスポンス</returns> public override TResponse BlockingUnaryCall <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, TRequest request) { double elapsed = 0; try { method = GetCustomMethod <TRequest, TResponse>(method); OnInvokingMethod(method, host, options, request); Stopwatch watch = null; TResponse result; try { watch = Stopwatch.StartNew(); result = m_Invoker.BlockingUnaryCall(method, host, options, request); } finally { elapsed = GrpcPerformanceListener.GetMilliseconds(watch); } OnInvokedMethod(method, host, options, request, elapsed); return(result); } catch (Exception ex) { GrpcExceptionListener.NotifyCatchClientException(method, host, options, ex); Exception alternate; if (HandleException(method, host, options, ex, out alternate)) { throw alternate; } else { throw; } } }
/// <summary> /// ServerStreaming メソッドを非同期で呼び出します。 /// </summary> /// <typeparam name="TRequest">リクエストの型</typeparam> /// <typeparam name="TResponse">レスポンスの型</typeparam> /// <param name="method">メソッド</param> /// <param name="host">ホスト</param> /// <param name="options">オプション</param> /// <param name="request">リクエスト</param> /// <returns>呼び出しオブジェクト</returns> public override AsyncServerStreamingCall <TResponse> AsyncServerStreamingCall <TRequest, TResponse>(Method <TRequest, TResponse> method, string host, CallOptions options, TRequest request) { double elapsed = 0; try { method = GetCustomMethod <TRequest, TResponse>(method); OnInvokingMethod(method, host, options, request); Stopwatch watch = null; AsyncServerStreamingCall <TResponse> call; try { watch = Stopwatch.StartNew(); call = m_Invoker.AsyncServerStreamingCall(method, host, options, request); } finally { elapsed = GrpcPerformanceListener.GetMilliseconds(watch); } OnInvokedMethod(method, host, options, request, elapsed); return(GrpcCallInvokerContext.Regist <TRequest, TResponse>(call, method, host, options, m_Settings.PerformanceListener)); } catch (Exception ex) { GrpcExceptionListener.NotifyCatchClientException(method, host, options, ex); Exception alternate; if (HandleException(method, host, options, ex, out alternate)) { throw alternate; } else { throw; } } }
/// <summary> /// ClientStreaming メソッドを生成します。 /// </summary> /// <typeparam name="TRequest">リクエストの型</typeparam> /// <typeparam name="TResponse">レスポンスの型</typeparam> /// <param name="builderContext">コンテキスト</param> /// <returns>メソッド</returns> private ClientStreamingServerMethod <TRequest, TResponse> CreateClientStreamingServerMethod <TRequest, TResponse>(MethodBuildContext builderContext) where TRequest : class where TResponse : class { ClientStreamingServerMethod <TRequest, TResponse> method = builderContext.MethodImpl.CreateDelegate(typeof(ClientStreamingServerMethod <TRequest, TResponse>), builderContext.ServiceInstance) as ClientStreamingServerMethod <TRequest, TResponse>; GrpcServerPerformanceListener performanceListener = builderContext.NeedNotifyPerformanceLog ? builderContext.Settings.PerformanceListener : null; return(async delegate(IAsyncStreamReader <TRequest> requestStream, ServerCallContext context) { try { await OnExecutingServiceMethodAsync(context, builderContext.InvokingInterceptors, performanceListener).ConfigureAwait(false); if (performanceListener != null) { performanceListener.NotifyMethodCalling(context); } TResponse result; Stopwatch watch = Stopwatch.StartNew(); double elapsd; try { result = await method( new RequestStreamReader <TRequest>(requestStream, 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); return result; } 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; } } }); }