internal void AddGenericEventHandler <TEventArgs>(RpcStub <TService> serviceStub, RpcEventInfo eventInfo, TMethodBinder binder) where TEventArgs : class { if (eventInfo.Event.EventHandlerType == null || eventInfo.Event.AddMethod == null || eventInfo.Event.RemoveMethod == null) { throw new NotSupportedException($"Service event handler for '{eventInfo.DeclaringMember.Name}' must be full defined."); } var serviceParameter = Expression.Parameter(typeof(TService)); var delegateParameter = Expression.Parameter(typeof(Delegate)); var castDelegateExpression = Expression.Convert(delegateParameter, eventInfo.Event.EventHandlerType); var addHandlerExpression = Expression.Call(serviceParameter, eventInfo.Event.AddMethod, castDelegateExpression); var addHandlerAction = Expression.Lambda <Action <TService, Delegate> >(addHandlerExpression, serviceParameter, delegateParameter).Compile(); var removeHandlerExpression = Expression.Call(serviceParameter, eventInfo.Event.RemoveMethod, castDelegateExpression); var removeHandlerAction = Expression.Lambda <Action <TService, Delegate> >(removeHandlerExpression, serviceParameter, delegateParameter).Compile(); ValueTask LocalBeginEventProducer(RpcObjectRequest request, IServiceProvider?serviceProvider, IRpcAsyncStreamWriter <TEventArgs> responseStream, IRpcContext context) { var eventProducer = new GenericEventHandlerProducer <TEventArgs>(responseStream, addHandlerAction, removeHandlerAction, context.CancellationToken); return(serviceStub.BeginEventProducer(request, serviceProvider, eventProducer)); } this.AddEventHandlerDefinition <TEventArgs>(eventInfo, LocalBeginEventProducer, serviceStub, binder); }
protected abstract void AddGenericVoidBlockingMethodCore <TRequest>( Action <TService, TRequest, CancellationToken> serviceCaller, RpcServerFaultHandler faultHandler, RpcStub <TService> serviceStub, RpcOperationInfo operationInfo, TMethodBinder binder) where TRequest : class, IObjectRequest;
protected abstract void AddGenericBlockingMethodCore <TRequest, TReturn, TResponseReturn>( Func <TService, TRequest, CancellationToken, TReturn> serviceCaller, Func <TReturn, TResponseReturn>?responseConverter, RpcServerFaultHandler faultHandler, RpcStub <TService> serviceStub, RpcOperationInfo operationInfo, TMethodBinder binder) where TRequest : class, IObjectRequest;
where TResponseReturn : class; // Needs to be class due to gRPC restriction protected abstract void AddCallbackMethodCore <TRequest, TReturn, TResponseReturn>( Func <TService, TRequest, Action <TReturn>, CancellationToken, Task> serviceCaller, Func <TReturn, TResponseReturn>?responseConverter, RpcServerFaultHandler faultHandler, RpcStub <TService> serviceStub, RpcOperationInfo operationInfo, TMethodBinder binder) where TRequest : class, IObjectRequest where TResponseReturn : class; // Needs to be class due to gRPC constraint
protected abstract void AddServerStreamingMethodCore <TRequest, TReturn, TResponseReturn>( Func <TService, TRequest, CancellationToken, IAsyncEnumerable <TReturn> > serviceCaller, Func <TReturn, TResponseReturn>?responseConverter, RpcServerFaultHandler faultHandler, RpcStub <TService> serviceStub, RpcOperationInfo operationInfo, TMethodBinder binder) where TRequest : class, IObjectRequest where TResponseReturn : class; // Needs to be class due to gRPC restriction
internal void AddEventHandler(RpcStub <TService> serviceStub, RpcEventInfo eventInfo, TMethodBinder binder) { if (typeof(EventHandler).Equals(eventInfo.Event.EventHandlerType)) { this.AddPlainEventHandler(serviceStub, eventInfo, binder); return; } // TODO: Cache. var addEventHandlerDelegate = (Action <RpcStub <TService>, RpcEventInfo, TMethodBinder>) GetBuilderMethod(nameof(this.AddGenericEventHandler)) .MakeGenericMethod(eventInfo.EventArgsType) .CreateDelegate(typeof(Action <RpcStub <TService>, RpcEventInfo, TMethodBinder>), this); addEventHandlerDelegate(serviceStub, eventInfo, binder); }
/// <summary> /// Generates the RPC method definitions and stub handlers and adds them to the provided methodBinder. /// </summary> /// <returns></returns> public RpcStub <TService> GenerateOperationHandlers(IRpcServerCore server, TMethodBinder methodBinder) { this.serviceStub = this.CreateServiceStub(server); foreach (var memberInfo in RpcBuilderUtil.EnumOperationHandlers(this.ServiceInfo, true)) { if (memberInfo is RpcEventInfo eventInfo) { this.AddEventHandler(this.serviceStub, eventInfo, methodBinder); } else if (memberInfo is RpcOperationInfo opInfo) { switch (opInfo.MethodType) { case RpcMethodType.Unary: this.CheckMethod(opInfo); this.AddUnaryMethod(this.serviceStub, opInfo, methodBinder); break; case RpcMethodType.ServerStreaming: this.CheckMethod(opInfo); if (opInfo.CallbackParameterIndex == null) { // No callback. Implement using IAsyncEnumerable this.AddServerStreamingMethod(this.serviceStub, opInfo, methodBinder); } else { // Implement using callback this.AddCallbackMethod(this.serviceStub, opInfo, methodBinder); } break; default: throw new NotImplementedException(); } } else { throw new NotImplementedException(); } } return(this.serviceStub); }
protected void AddGenericBlockingMethod <TRequest, TReturn, TResponseReturn>(RpcStub <TService> serviceStub, RpcOperationInfo opInfo, TMethodBinder binder) where TRequest : class, IObjectRequest { if (opInfo is null) { throw new ArgumentNullException(nameof(opInfo)); } Func <TReturn, TResponseReturn>?responseCreator = GetResponseCreator <TReturn, TResponseReturn>(opInfo); RpcServerFaultHandler faultHandler = this.CreateFaultHandler(opInfo); if (opInfo.IsAsync) { var serviceCaller = GenerateUnaryMethodHandler <TRequest, TReturn>(opInfo); this.AddGenericAsyncMethodCore(serviceCaller, responseCreator, faultHandler, serviceStub, opInfo, binder); } else { var serviceCaller = GenerateBlockingUnaryMethodHandler <TRequest, TReturn>(opInfo); this.AddGenericBlockingMethodCore(serviceCaller, responseCreator, faultHandler, serviceStub, opInfo, binder); } }
protected void AddGenericServerStreamingMethod <TRequest, TReturn, TResponseReturn>(RpcStub <TService> serviceStub, RpcOperationInfo opInfo, TMethodBinder binder) where TRequest : class, IObjectRequest where TResponseReturn : class // Needs to be class due to gRPC constraint { if (opInfo is null) { throw new ArgumentNullException(nameof(opInfo)); } Func <TReturn, TResponseReturn>?responseCreator = GetResponseCreator <TReturn, TResponseReturn>(opInfo); RpcServerFaultHandler faultHandler = this.CreateFaultHandler(opInfo); var serviceCaller = GenerateServerStreamingMethodHandler <TRequest, TReturn>(opInfo); this.AddServerStreamingMethodCore(serviceCaller, responseCreator, faultHandler, serviceStub, opInfo, binder); }
protected abstract void AddEventHandlerDefinition <TEventArgs>( RpcEventInfo eventInfo, Func <RpcObjectRequest, IServiceProvider?, IRpcAsyncStreamWriter <TEventArgs>, IRpcContext, ValueTask> beginEventProducer, RpcStub <TService> serviceStub, TMethodBinder binder) where TEventArgs : class;