/// <summary> /// Создает из списка обработчиков пайплайн обработки входящего запроса. /// Последним обработчиком всегда будет являться <see cref="CommandExecutorMiddleware"/> /// </summary> public void CreateChainMiddlewareCall() { // Добавляем CommandExecutorMiddleware, она отвечает за маршрутизацию экшенов, эвентов и стейт машины MiddlewareExecutor.AddMiddleware(typeof(CommandExecutorMiddleware)); using var scope = serviceScopeFactory.CreateScope(); MiddlewareData prevMiddleware = null; foreach (var middleware in Enumerable.Reverse(Middlewares)) { var constructor = middleware.Class.GetConstructors().FirstOrDefault(x => x.GetParameters().Any(param => param.ParameterType == typeof(BotMiddlewareHandler))); if (constructor == null) { throw new Exception("The constructor must accept a parameter of type NextExpressMiddleware"); } var constructorParameterInstances = constructor.GetParameters() .Select( x => x.ParameterType == typeof(BotMiddlewareHandler) ? CreateDelegate(prevMiddleware) : scope.ServiceProvider.GetService(x.ParameterType) ); var instanse = Activator.CreateInstance(middleware.Class, constructorParameterInstances.ToArray()); middleware.Instance = instanse; prevMiddleware = middleware; } }
private BotMiddlewareHandler CreateDelegate(MiddlewareData nextMiddleware) { if (nextMiddleware == null) { return(null); } return(async delegate(UserMessage message) { using var scope = serviceScopeFactory.CreateScope(); var parameters = nextMiddleware.Parameters .Select(x => x == typeof(UserMessage) ? message : scope.ServiceProvider.GetService(x)) .ToArray(); await nextMiddleware.Method.InvokeAsync(nextMiddleware.Instance, parameters); }); }
/// <summary> /// Добавляем обработчик в список обработчиков. /// </summary> /// <param name="middlewareClass"></param> public static void AddMiddleware(Type middlewareClass) { var method = middlewareClass.GetMethod("Invoke") ?? middlewareClass.GetMethod("InvokeAsync"); if (method == null) { throw new Exception($"{middlewareClass.Name} does not contain a method 'Invoke' or 'InvokeAsync'"); } if (!method.GetParameters().Any(x => x.ParameterType == typeof(UserMessage))) { throw new Exception($"UserMessage is require param"); } var middleware = new MiddlewareData(); middleware.Class = middlewareClass; middleware.Method = new FastMethodInfo(method); middleware.Parameters = method.GetParameters().Select(x => x.ParameterType).ToList(); Middlewares.Add(middleware); }