/// <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);
            }
        }
Esempio n. 4
0
        /// <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);
        }