/// <summary>
        /// Build server grpc
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="cfg"></param>
        /// <returns></returns>
        internal static Grpc.Core.Server Build(IServiceProvider provider, GrpcServerConfiguration cfg)
        {
            // get logger if needed
            var logger = (cfg.Options?.LogRequests ?? false) ? provider.GetService <ILoggerFactory>()?.CreateLogger("GrpcServerRequests") : null;

            // create services for interfaces
            var interfacesServices = CreateServiceDefinitionForInterfaces(provider, cfg);

            // implemented services
            var protoGenServices = CreateServicesDefinitionsForProtoGen(provider, cfg);

            // create grpc server
            var server = new Grpc.Core.Server()
            {
                Ports    = { { cfg.Host.Url, cfg.Host.Port, ServerCredentials.Insecure } },
                Services = {}
            };

            // add services to server
            interfacesServices.ForEach(s => server.Services.Add(s));
            protoGenServices.ForEach(s => server.Services.Add(s));

            // return server
            return(server);
        }
Exemple #2
0
 /// <summary>
 /// Constructor with server and configuration as parameters
 /// </summary>
 /// <param name="provider"></param>
 /// <param name="cfg"></param>
 internal GrpcHost(IServiceProvider provider, GrpcServerConfiguration cfg)
 {
     Configuration = cfg;
     _provider     = provider;
     if (cfg.Options.StatsEnabled)
     {
         Stats = new GrpcStats();
     }
 }
        /// <summary>
        /// Add grpc method to definition builder
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <typeparam name="TService"></typeparam>
        /// <param name="provider"></param>
        /// <param name="builder"></param>
        /// <param name="method"></param>
        /// <param name="handler"></param>
        /// <param name="cfg"></param>
        public static void AddGrpcMethodToDefinitionBuilder <TRequest, TResponse, TService>(
            IServiceProvider provider,
            ServerServiceDefinition.Builder builder,
            Method <TRequest, TResponse> method,
            Func <TService, TRequest, CancellationToken,
                  Task <TResponse> > handler,
            GrpcServerConfiguration cfg)
            where TService : class
            where TRequest : class
            where TResponse : class
        {
            // get host stats
            var stats = provider.GetServices <GrpcHost>().FirstOrDefault(h => h.Name == cfg.Name)?.Stats;

            // add method
            builder.AddMethod(method, async(req, responseStream, context) => {
                await RequestHandler.HandleRequest <TRequest, TResponse, TService>(provider, req, handler, cfg.Name, method.Name, context, responseStream);
            });
        }
        /// <summary>
        /// Get service definition for interfaces
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="cfg"></param>
        /// <returns></returns>
        private static List <ServerServiceDefinition> CreateServiceDefinitionForInterfaces(IServiceProvider provider, GrpcServerConfiguration cfg)
        {
            // get types to create services for
            var servicesTypes = cfg.ServicesTypes
                                .Where(t => t.IsInterface && t.GetMethods(BindingFlags.Public | BindingFlags.Instance).Any());

            // create services
            var services = servicesTypes.Select(type => {
                // create builder
                var builder = ServerServiceDefinition.CreateBuilder();

                // register methods
                var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance).ToList();
                methods.ForEach(m => RegisterServiceMethodToGrpc(m, provider, builder, cfg));

                // build interfaces services
                var service = builder.Build();
                return(service);
            }).ToList();

            // return
            return(services);
        }
        /// <summary>
        /// Create services definitions for proto generated services
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="cfg"></param>
        /// <returns></returns>
        private static List <ServerServiceDefinition> CreateServicesDefinitionsForProtoGen(IServiceProvider provider, GrpcServerConfiguration cfg)
        {
            // create definitions
            var servicesImpl = cfg.ServicesTypes.Where(t => !t.IsInterface).Select(svcType =>
            {
                // get bind method from generated code
                var baseType = GrpcProtoServiceTypeBuilder.Build(svcType, cfg.Name);

                // var baseType = svcType.BaseType;
                var bind       = (BindServiceMethodAttribute)baseType.GetCustomAttributes().First(a => a.GetType() == typeof(BindServiceMethodAttribute));
                var bindMethod = bind.BindType.GetMethod(bind.BindMethodName, new Type[] { baseType });

                // create service intstance and bind
                var svc = Activator.CreateInstance(baseType, new object[] { provider });
                ServerServiceDefinition svcs = (ServerServiceDefinition)bindMethod.Invoke(null, new object[] { svc });
                return(svcs);
            }).ToList();

            // return
            return(servicesImpl);
        }
        /// <summary>
        /// Register service methods to grpc
        /// </summary>
        /// <param name="method"></param>
        /// <param name="provider"></param>
        /// <param name="builder"></param>
        /// <param name="cfg"></param>
        public static void RegisterServiceMethodToGrpc(MethodInfo method, IServiceProvider provider,
                                                       ServerServiceDefinition.Builder builder, GrpcServerConfiguration cfg)
        {
            // get service data
            var serviceType = method.DeclaringType;
            var serviceName = serviceType.Name;

            // get method data
            var methodName   = method.Name;
            var requestType  = method.GetParameters()[0].ParameterType;
            var responseType = method.ReturnType.GenericTypeArguments[0];

            // create grpc method
            var grpcMethodFnc = typeof(GrpcMethodFactoryUtil).GetMethod(nameof(GrpcMethodFactoryUtil.CreateGrpcMethod)).MakeGenericMethod(requestType, responseType);
            var grpcMethod    = grpcMethodFnc.Invoke(null, new object[] { serviceName, methodName });

            // create grpc method handler
            var grpcMethodHandlerFnc = typeof(GrpcServerBuilder).GetMethod(nameof(GrpcServerBuilder.GenerateGrpcUnaryMethodHandler)).
                                       MakeGenericMethod(serviceType, requestType, responseType);
            var grpcMethodHandler = grpcMethodHandlerFnc.Invoke(null, new object[] { method });

            // add method to services builder
            var addMethodFnc = typeof(GrpcServerBuilder).GetMethod(nameof(GrpcServerBuilder.AddGrpcMethodToDefinitionBuilder)).
                               MakeGenericMethod(requestType, responseType, serviceType);

            addMethodFnc.Invoke(null, new object[] { provider, builder, grpcMethod, grpcMethodHandler, cfg });
        }