/// <summary> /// Maps incoming requests to the specified <typeparamref name="TService"/> type. /// </summary> /// <typeparam name="TService">The service type to map requests to.</typeparam> /// <param name="builder">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param> /// <param name="configureOptions">A callback to configure binding options.</param> /// <returns>An <see cref="IEndpointConventionBuilder"/> for endpoints associated with the service.</returns> public static IEndpointConventionBuilder MapGrpcService <TService>(this IEndpointRouteBuilder builder, Action <GrpcBindingOptions <TService> > configureOptions) where TService : class { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } ValidateServicesRegistered(builder.ServiceProvider); var options = new GrpcBindingOptions <TService>(); options.BindAction = ReflectionBind; options.ModelFactory = new ReflectionMethodModelFactory <TService>(); configureOptions?.Invoke(options); var callHandlerFactory = builder.ServiceProvider.GetRequiredService <ServerCallHandlerFactory <TService> >(); var serviceMethodsRegistry = builder.ServiceProvider.GetRequiredService <ServiceMethodsRegistry>(); var loggerFactory = builder.ServiceProvider.GetRequiredService <ILoggerFactory>(); var serviceBinder = new GrpcServiceBinder <TService>(builder, options.ModelFactory, callHandlerFactory, serviceMethodsRegistry, loggerFactory); try { options.BindAction(serviceBinder, null); } catch (Exception ex) { throw new InvalidOperationException($"Error binding gRPC service '{typeof(TService).Name}'.", ex); } serviceBinder.CreateUnimplementedEndpoints(); return(new CompositeEndpointConventionBuilder(serviceBinder.EndpointConventionBuilders)); }
public static IEndpointConventionBuilder MapGrpcService <TService>(this IEndpointRouteBuilder builder) where TService : class { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } ValidateServicesRegistered(builder.ServiceProvider); var service = typeof(TService); try { // TService is an implementation of the gRPC service. It ultimately derives from Foo.TServiceBase base class. // We need to access the static BindService method on Foo which implicitly derives from Object. var baseType = service.BaseType; while (baseType?.BaseType?.BaseType != null) { baseType = baseType.BaseType; } // We need to call Foo.BindService from the declaring type. var declaringType = baseType?.DeclaringType; // The method we want to call is public static void BindService(ServiceBinderBase serviceBinder) var bindService = declaringType?.GetMethod("BindService", new[] { typeof(ServiceBinderBase), baseType }); if (bindService == null) { throw new InvalidOperationException($"Cannot locate BindService(ServiceBinderBase, ServiceBase) method for the current service type: {service.FullName}. The type must be an implementation of a gRPC service."); } var serviceBinder = new GrpcServiceBinder <TService>(builder); // Create dummy service instance for the call to BindService. // This will fail for services that resolve Scoped services in the constructor. // This restriction will be fixed by https://github.com/grpc/grpc-dotnet/issues/21 var dummy = new DefaultGrpcServiceActivator <TService>(builder.ServiceProvider).Create(); // Invoke bindService.Invoke(null, new object[] { serviceBinder, dummy }); return(new CompositeEndpointConventionBuilder(serviceBinder.EndpointConventionBuilders)); } catch (Exception ex) { throw new InvalidOperationException($"Unable to map gRPC service '{service.Name}'.", ex); } }
public static IEndpointConventionBuilder MapGrpcService <TService>(this IEndpointRouteBuilder builder) where TService : class { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } ValidateServicesRegistered(builder.ServiceProvider); var service = typeof(TService); try { // TService is an implementation of the gRPC service. It ultimately derives from Foo.TServiceBase base class. // We need to access the static BindService method on Foo which implicitly derives from Object. var baseType = service.BaseType; while (baseType?.BaseType?.BaseType != null) { baseType = baseType.BaseType; } // We need to call Foo.BindService from the declaring type. var declaringType = baseType?.DeclaringType; // The method we want to call is public static void BindService(ServiceBinderBase, BaseType) var bindService = declaringType?.GetMethod("BindService", new[] { typeof(ServiceBinderBase), baseType }); if (bindService == null) { throw new InvalidOperationException($"Cannot locate BindService(ServiceBinderBase, ServiceBase) method for the current service type: {service.FullName}. The type must be an implementation of a gRPC service."); } var callHandlerFactory = builder.ServiceProvider.GetRequiredService <ServerCallHandlerFactory <TService> >(); var serviceBinder = new GrpcServiceBinder <TService>(builder, callHandlerFactory); // Invoke bindService.Invoke(null, new object[] { serviceBinder, null }); return(new CompositeEndpointConventionBuilder(serviceBinder.EndpointConventionBuilders)); } catch (Exception ex) { throw new InvalidOperationException($"Unable to map gRPC service '{service.Name}'.", ex); } }
/// <summary> /// 使用DashBoard(提供基础服务) /// </summary> /// <returns></returns> public ServerBuilder UseDashBoard() { var serviceBinder = new GrpcServiceBinder(); foreach (var serviceDefinition in _serviceDefinitions) { var bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; /* * //生成Grpc元数据信息(1.19以前可以反射处理) * var callHandlers = serviceDefinition.GetPropertyValue<IDictionary>("CallHandlers", bindingFlags); * GrpcServiceExtension.BuildMeta(callHandlers); */ //生成Grpc元数据信息(1.19以后使用自定义serviceBinder) var bindMethodInfo = serviceDefinition.GetType().GetMethodInfo("BindService", bindingFlags); bindMethodInfo.Invoke(serviceDefinition, new[] { serviceBinder }); } //注册基础服务 UseGrpcService(new List <IGrpcService> { new CmdService(), new MetaService() }); return(this); }