using Grpc.Extension; using Grpc.Extension.Abstract; using Grpc.Extension.BaseService; using Grpc.Extension.Client; using Grpc.Extension.Common.Internal; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.Extensions.DependencyInjection; using OpenTracing; using OpenTracing.Util; using System; using System.Linq; using System.Runtime.InteropServices; namespace Grpc.Extension.AspNetCore { public static class IApplicationBuilderExtensions { /// /// 使用Grpc扩展 /// /// 实现IGrpcService的类所在程序集下的任意类 /// /// /// public static IApplicationBuilder UseGrpcExtensions(this IApplicationBuilder builder, Action configureOptions = null) { ServiceProviderAccessor.SetServiceProvider(builder.ApplicationServices); //注入基本配制 configureOptions?.Invoke(GrpcExtensionsOptions.Instance); //使用基础服务 builder.UseEndpoints(endpoints => { endpoints.MapIGrpcServices(); //使用基础服务 endpoints.MapGrpcService(); endpoints.MapGrpcService(); }); //默认使用 builder.InitGrpcOptions()//初始化配制 .UseLoggerFactory()//使用LoggerFactory .UseJaeger();//使用Jaeger return builder; } /// /// MapGrpcService(TStartup程序集下所有的IGrpcService) /// /// 实现IGrpcService的类所在程序集下的任意类 /// public static void MapIGrpcServices(this IEndpointRouteBuilder endpoints) { //获取所有IGrpcService并调用MapGrpcService方法 var grpcServices = typeof(TStartup).Assembly.GetTypes().Where(p => typeof(IGrpcService).IsAssignableFrom(p) && p.IsClass); var method = typeof(GrpcEndpointRouteBuilderExtensions).GetMethod("MapGrpcService"); foreach (var service in grpcServices) { var mapGrpcService = method.MakeGenericMethod(service); mapGrpcService.Invoke(null, new object[] { endpoints }); } } /// /// 初始化配制 /// /// /// private static IApplicationBuilder InitGrpcOptions(this IApplicationBuilder builder) { var provider = builder.ApplicationServices; var serverOptions = provider.GetService>().Value; //Jaeger配置 if (serverOptions.Jaeger != null && string.IsNullOrWhiteSpace(serverOptions.Jaeger.ServiceName)) serverOptions.Jaeger.ServiceName = serverOptions.DiscoveryServiceName; #region 默认的客户端配制 var clientOptions = provider.GetService>().Value; clientOptions.DiscoveryUrl = serverOptions.DiscoveryUrl; clientOptions.DefaultErrorCode = serverOptions.DefaultErrorCode; clientOptions.Jaeger = serverOptions.Jaeger; clientOptions.GrpcCallTimeOut = serverOptions.GrpcCallTimeOut; #endregion return builder; } /// /// 注入Grpc,Discovery配制 /// /// /// /// public static IApplicationBuilder UseGrpcOptions(this IApplicationBuilder builder, Action configureOptions) { var options = ServiceProviderAccessor.GetService>().Value; configureOptions(options); return builder; } /// /// 有Jaeger配制就使用Jaeger /// /// /// private static IApplicationBuilder UseJaeger(this IApplicationBuilder builder) { var serverOptions = ServiceProviderAccessor.GetService>().Value; if (serverOptions.Jaeger != null && string.IsNullOrWhiteSpace(serverOptions.Jaeger.ServiceName)) serverOptions.Jaeger.ServiceName = serverOptions.DiscoveryServiceName; if (serverOptions.Jaeger?.CheckConfig() == true) { var tracer = ServiceProviderAccessor.GetService(); if (tracer != null) GlobalTracer.Register(tracer); } return builder; } /// /// 使用LoggerFactory /// /// /// private static IApplicationBuilder UseLoggerFactory(this IApplicationBuilder builder) { var loggerFactory = ServiceProviderAccessor.GetService(); var logger = loggerFactory.CreateLogger(); var loggerAccess = loggerFactory.CreateLogger("grpc.access"); LoggerAccessor.Instance.LoggerError += (ex, type) => logger.LogError(ex.ToString()); LoggerAccessor.Instance.LoggerMonitor += (msg, type) => loggerAccess.LogInformation(msg); return builder; } /// /// 配制日志(默认使用LoggerFactory) /// /// /// /// public static IApplicationBuilder UseLogger(this IApplicationBuilder builder, Action configureLogger) { configureLogger(LoggerAccessor.Instance); return builder; } /// /// CodeFirst生成proto文件 /// /// /// 生成目录 /// 是否拆分service和message协议 /// public static IApplicationBuilder UseProtoGenerate(this IApplicationBuilder builder, string dir, bool spiltProto = true) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ProtoGenerator.Gen(dir, spiltProto); return builder; } } }