예제 #1
0
 public void Use(UpdateProcessingDelegate middlewareDelegate)
 {
     if (middlewareDelegate == null)
     {
         throw new ArgumentNullException(nameof(middlewareDelegate));
     }
     _updateProcessingDelegates.Push(middlewareDelegate);
 }
예제 #2
0
 // 共通処理
 private void CommonUpdate(UpdateProcessingDelegate onUpdate)
 {
     for (int i = 0; i < m_ringBuffer.Length; i++)
     {
         if (!m_ringBuffer[i].gameObject.activeSelf)
         {
             continue;
         }
         onUpdate(m_ringBuffer[i]);
     }
 }
예제 #3
0
        public UpdateProcessingDelegate Build()
        {
            //For each new iteration and each middleware from stack processingDelegate_OfIteration will contain delegate to execute
            //all next middleware.
            //"next" delegate for current iteration. Started with empty delegate for last middleware.
            UpdateProcessingDelegate processingDelegate_OfIteration = async(UpdateContext ctx, Func <Task> nextFunc) => { };

            while (_updateProcessingDelegates.Count > 0)
            {
                var prevProcessingDelegate    = processingDelegate_OfIteration;
                var currentProcessingDelegate = _updateProcessingDelegates.Pop();

                processingDelegate_OfIteration = async(UpdateContext ctx, Func <Task> mostNext) =>
                {
                    Func <Task> next = async() =>
                    {
                        await prevProcessingDelegate.Invoke(ctx, mostNext);
                    };

                    //Force exit.
                    if (ctx.ForceExitRequested)
                    {
                        return;
                    }

                    //Execute current.
                    await currentProcessingDelegate.Invoke(ctx, next);
                };
            }

            //Just add some checks.
            UpdateProcessingDelegate res = async(UpdateContext ctx, Func <Task> next) =>
            {
                if (ctx == null)
                {
                    throw new ArgumentNullException(nameof(ctx), "Null context passed to UpdateProcessingDelegate.");
                }
                if (next == null)
                {
                    throw new ArgumentNullException(nameof(next), "Null 'next' passed to UpdateProcessingDelegate.");
                }
                await processingDelegate_OfIteration.Invoke(ctx, next);
            };

            return(res);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="disposeServices">Default is true.</param>
        public async void Dispose(bool disposeServices)
        {
            if (IsDisposed)
            {
                return;
            }
            await Stop();

            if (disposeServices)
            {
                //Dispose singletones that registered to be disposed.
                foreach (var type in _forDispose)
                {
                    IDisposable serviceToDispose = null;
                    try
                    {
                        serviceToDispose = Services.GetService(type) as IDisposable;
                    }
                    catch
                    {
                    }

                    serviceToDispose?.Dispose();
                }
                (Services as IDisposable)?.Dispose();
            }

            Services = null;

            BotContext = null;
            _updateProcessingDelegate = null;
            IsDisposed = true;
            _updatesReceiver.BotManagerDisposed();
            GC.Collect();
            _logger.LogTrace(nameof(BotManager) + " disposed.");
        }
        /// <summary>
        /// Execute initialization callbacks and build pipeline.
        /// <para></para>
        /// Called automatically on Start() first call.
        /// </summary>
        /// <param name="serviceProvider">
        /// If not null - will use passed provider instead builded from service collection.
        /// Useful when you wan't to set same container in ASP.NET and here.
        /// </param>
        /// <param name="updatesReceiver">
        /// Use it to customize how bot receiving updates.
        /// Default is <see cref="PollingUpdatesReceiver"/> and subscribe on <see cref="ITelegramBotClient.OnUpdate"/>.
        /// It will set webhook string empty, to enable polling.
        /// </param>
        public void Setup(IServiceProvider serviceProvider = null, IUpdatesReceiver updatesReceiver = null)
        {
            //?Why use IUpdatesReceiver? Why not just make ProcessUpdate method public?
            //Was decided to use interface with event to wrote more "infrastructure" code in BotManager.

            lock (_setupLocker)
            {
                try
                {
                    if (_isSetup)
                    {
                        return;
                    }

                    //Init bot context.
                    var botInfo = _bot.GetMeAsync().Result;
                    BotContext = new BotClientContext(_bot, botInfo);

                    //Set UpdateReceiver.
                    _updatesReceiver = updatesReceiver ?? new PollingUpdatesReceiver();
                    _updatesReceiver.Init(this);

                    //Build service provider.
                    string providerIndentifierForLog;
                    if (serviceProvider == null)
                    {
                        Services = _serviceCollectionWrapper.Services.BuildServiceProvider();
                        providerIndentifierForLog = "ServiceProvider builded from ServiceCollection.";
                    }
                    else
                    {
                        Services = serviceProvider;
                        providerIndentifierForLog = "Passed ServiceProvider used.";
                    }
                    _serviceCollectionWrapper = null;

                    //Resolve services needed for BotManager.
                    ResolveBotManagerServices();
                    _logger.LogTrace("Services initialized. " + providerIndentifierForLog);

                    //Not implemented.
                    IPipelineBuilder pipelineBuilder = new PipelineBuilder(Services);

                    //Register middleware.
                    UseMandatoryMiddleware(pipelineBuilder);
                    if (_pipelineBuilderAction == null)
                    {
                        throw new NullReferenceException(
                                  "Can`t init without pipeline builder configure action. " +
                                  "Probably ConfigureBuilder wasn't invoked."
                                  );
                    }
                    _pipelineBuilderAction.Invoke(pipelineBuilder);
                    _pipelineBuilderAction = null;

                    //Build pipeline.
                    _updateProcessingDelegate = pipelineBuilder.Build();
                    _isSetup = true;
                    _logger.LogTrace("Pipeline builded.");
                }
                catch (Exception ex)
                {
                    var exception = new TelegramAspException("BotManager setup exception.", ex);
                    if (_logger == null)
                    {
                        Debug.WriteLine(exception.ToString());
                    }
                    else
                    {
                        _logger.LogError(exception, "");
                    }
                    throw exception;
                }
            }
        }