Also simplified Generic Host building

This commit is contained in:
2026-03-06 21:02:19 +04:00
parent 1e4a474beb
commit 516367c602
6 changed files with 128 additions and 114 deletions
@@ -3,16 +3,11 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Text;
using Telegram.Bot.Types.Enums;
using Telegrator.Configuration;
using Telegrator.Hosting.Components; using Telegrator.Hosting.Components;
using Telegrator.Hosting.Web.Components; using Telegrator.Hosting.Web.Components;
using Telegrator.MadiatorCore; using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
namespace Telegrator.Hosting.Web namespace Telegrator.Hosting.Web
{ {
+2 -27
View File
@@ -5,16 +5,13 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Diagnostics; using System.Diagnostics;
using System.Text;
using Telegram.Bot; using Telegram.Bot;
using Telegram.Bot.Types.Enums;
using Telegrator.Configuration; using Telegrator.Configuration;
using Telegrator.Hosting.Providers; using Telegrator.Hosting.Providers;
using Telegrator.Hosting.Providers.Components; using Telegrator.Hosting.Providers.Components;
using Telegrator.Hosting.Web.Components; using Telegrator.Hosting.Web.Components;
using Telegrator.Hosting.Web.Polling; using Telegrator.Hosting.Web.Polling;
using Telegrator.MadiatorCore; using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
namespace Telegrator.Hosting.Web namespace Telegrator.Hosting.Web
{ {
@@ -96,8 +93,8 @@ namespace Telegrator.Hosting.Web
ILoggerFactory loggerFactory = app.Services.GetRequiredService<ILoggerFactory>(); ILoggerFactory loggerFactory = app.Services.GetRequiredService<ILoggerFactory>();
ILogger logger = loggerFactory.CreateLogger("Telegrator.Hosting.Web.TelegratorHost"); ILogger logger = loggerFactory.CreateLogger("Telegrator.Hosting.Web.TelegratorHost");
logger.LogInformation("Telegrator Bot WebHost started"); logger.LogInformation("Telegrator Bot ASP.NET WebHost started");
LogHandlers(handlers, logger); logger.LogHandlers(handlers);
return app; return app;
} }
@@ -116,27 +113,5 @@ namespace Telegrator.Hosting.Web
private static ITelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider) private static ITelegramBotClient TypedTelegramBotClientFactory(HttpClient httpClient, IServiceProvider provider)
=> new TelegramBotClient(provider.GetRequiredService<IOptions<TelegramBotClientOptions>>().Value, httpClient); => new TelegramBotClient(provider.GetRequiredService<IOptions<TelegramBotClientOptions>>().Value, httpClient);
private static void LogHandlers(IHandlersCollection handlers, ILogger logger)
{
if (!handlers.Keys.Any())
throw new Exception("No handlers were registered for the bot.");
StringBuilder logBuilder = new StringBuilder("Registered handlers : ");
foreach (UpdateType updateType in handlers.Keys)
{
HandlerDescriptorList descriptors = handlers[updateType];
logBuilder.Append("\n\tUpdateType." + updateType + " :");
foreach (HandlerDescriptor descriptor in Enumerable.Reverse(descriptors))
{
logBuilder.AppendFormat("\n\t* {0} - {1}",
descriptor.Indexer.ToString(),
descriptor.ToString());
}
}
logger.LogInformation(logBuilder.ToString());
}
} }
} }
@@ -13,7 +13,7 @@ namespace Telegrator.Hosting.Providers
/// Pre host building task /// Pre host building task
/// </summary> /// </summary>
/// <param name="builder"></param> /// <param name="builder"></param>
public delegate void PreBuildingRoutine(IApplicationBuilder builder); public delegate void PreBuildingRoutine(ITelegramBotHostBuilder builder);
/// <inheritdoc/> /// <inheritdoc/>
public class HostHandlersCollection(IServiceCollection hostServiceColletion, ITelegratorOptions options) : HandlersCollection(options), IHostHandlersCollection public class HostHandlersCollection(IServiceCollection hostServiceColletion, ITelegratorOptions options) : HandlersCollection(options), IHostHandlersCollection
+2 -39
View File
@@ -1,13 +1,8 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Text;
using Telegram.Bot.Types.Enums;
using Telegrator.Configuration;
using Telegrator.Hosting.Components; using Telegrator.Hosting.Components;
using Telegrator.MadiatorCore; using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
namespace Telegrator.Hosting namespace Telegrator.Hosting
{ {
@@ -47,16 +42,14 @@ namespace Telegrator.Hosting
// Building proxy hoster // Building proxy hoster
_innerHost = hostApplicationBuilder.Build(); _innerHost = hostApplicationBuilder.Build();
_serviceProvider = _innerHost.Services; _serviceProvider = _innerHost.Services;
_innerHost.UseTelegrator();
// Initializing bot info, as it requires to make a request via tg bot
Services.GetRequiredService<ITelegramBotInfo>();
// Reruesting services for this host // Reruesting services for this host
_updateRouter = Services.GetRequiredService<IUpdateRouter>(); _updateRouter = Services.GetRequiredService<IUpdateRouter>();
_logger = Services.GetRequiredService<ILogger<TelegramBotHost>>(); _logger = Services.GetRequiredService<ILogger<TelegramBotHost>>();
// Logging registering handlers in DEBUG purposes // Logging registering handlers in DEBUG purposes
LogHandlers(handlers); _logger.LogHandlers(handlers);
} }
/// <summary> /// <summary>
@@ -131,28 +124,6 @@ namespace Telegrator.Hosting
_disposed = true; _disposed = true;
} }
private void LogHandlers(IHandlersCollection handlers)
{
StringBuilder logBuilder = new StringBuilder("Registered handlers : ");
if (!handlers.Keys.Any())
throw new Exception();
foreach (UpdateType updateType in handlers.Keys)
{
HandlerDescriptorList descriptors = handlers[updateType];
logBuilder.Append("\n\tUpdateType." + updateType + " :");
foreach (HandlerDescriptor descriptor in descriptors.Reverse())
{
logBuilder.AppendFormat("\n\t* {0} - {1}",
descriptor.Indexer.ToString(),
descriptor.ToString());
}
}
Logger.LogInformation(logBuilder.ToString());
}
private void RegisterHostServices(IServiceCollection services, IHandlersCollection handlers) private void RegisterHostServices(IServiceCollection services, IHandlersCollection handlers)
{ {
//services.RemoveAll<IHost>(); //services.RemoveAll<IHost>();
@@ -160,14 +131,6 @@ namespace Telegrator.Hosting
services.AddSingleton<ITelegramBotHost>(this); services.AddSingleton<ITelegramBotHost>(this);
services.AddSingleton<ITelegratorBot>(this); services.AddSingleton<ITelegratorBot>(this);
services.AddSingleton(handlers);
if (handlers is IHandlersManager manager)
{
services.RemoveAll<IHandlersProvider>();
services.AddSingleton<IHandlersProvider>(manager);
services.AddSingleton(manager);
}
} }
} }
} }
+2 -39
View File
@@ -2,14 +2,8 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegrator.Hosting;
using Telegrator.Hosting.Components; using Telegrator.Hosting.Components;
using Telegrator.Hosting.Configuration;
using Telegrator.Hosting.Providers; using Telegrator.Hosting.Providers;
using Telegrator.Hosting.Providers.Components;
using Telegrator.MadiatorCore; using Telegrator.MadiatorCore;
#pragma warning disable IDE0001 #pragma warning disable IDE0001
@@ -50,6 +44,7 @@ namespace Telegrator.Hosting
_settings = settings ?? new TelegramBotHostBuilderSettings(); _settings = settings ?? new TelegramBotHostBuilderSettings();
_handlers = new HostHandlersCollection(Services, _settings); _handlers = new HostHandlersCollection(Services, _settings);
_innerBuilder.AddTelegrator(_settings, _handlers);
_innerBuilder.Logging.ClearProviders(); _innerBuilder.Logging.ClearProviders();
} }
@@ -65,6 +60,7 @@ namespace Telegrator.Hosting
_settings = settings ?? new TelegramBotHostBuilderSettings(); _settings = settings ?? new TelegramBotHostBuilderSettings();
_handlers = handlers ?? throw new ArgumentNullException(nameof(handlers)); _handlers = handlers ?? throw new ArgumentNullException(nameof(handlers));
_innerBuilder.AddTelegrator(_settings, _handlers);
_innerBuilder.Logging.ClearProviders(); _innerBuilder.Logging.ClearProviders();
} }
@@ -74,39 +70,6 @@ namespace Telegrator.Hosting
/// <returns></returns> /// <returns></returns>
public TelegramBotHost Build() public TelegramBotHost Build()
{ {
if (_handlers is IHostHandlersCollection hostHandlers)
{
foreach (PreBuildingRoutine preBuildRoutine in hostHandlers.PreBuilderRoutines)
{
try
{
preBuildRoutine.Invoke(this);
}
catch (NotImplementedException)
{
_ = 0xBAD + 0xC0DE;
}
}
}
if (!_settings.DisableAutoConfigure)
{
Services.Configure<ReceiverOptions>(Configuration.GetSection(nameof(ReceiverOptions)));
Services.Configure<TelegramBotClientOptions>(Configuration.GetSection(nameof(TelegramBotClientOptions)), new TelegramBotClientOptionsProxy());
}
else
{
/*
if (null == Services.SingleOrDefault(srvc => srvc.ImplementationType == typeof(IOptions<ReceiverOptions>)))
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'ReceiverOptions' wasn't registered. This configuration is runtime required!");
*/
if (null == Services.SingleOrDefault(srvc => srvc.ImplementationType == typeof(IOptions<TelegramBotClientOptions>)))
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegramBotClientOptions' wasn't registered. This configuration is runtime required!");
}
Services.AddSingleton<IOptions<TelegratorOptions>>(Options.Create(_settings));
Services.AddSingleton<IConfigurationManager>(Configuration);
return new TelegramBotHost(_innerBuilder, _handlers); return new TelegramBotHost(_innerBuilder, _handlers);
} }
} }
+121 -3
View File
@@ -1,22 +1,95 @@
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Reflection; using System.Reflection;
using System.Text;
using Telegram.Bot; using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Telegrator.Configuration; using Telegrator.Configuration;
using Telegrator.Hosting.Components; using Telegrator.Hosting.Components;
using Telegrator.Hosting.Configuration; using Telegrator.Hosting.Configuration;
using Telegrator.Hosting.Logging; using Telegrator.Hosting.Logging;
using Telegrator.Hosting.Polling; using Telegrator.Hosting.Polling;
using Telegrator.Hosting.Providers; using Telegrator.Hosting.Providers;
using Telegrator.Hosting.Providers.Components;
using Telegrator.Logging; using Telegrator.Logging;
using Telegrator.MadiatorCore; using Telegrator.MadiatorCore;
using Telegrator.MadiatorCore.Descriptors;
namespace Telegrator.Hosting namespace Telegrator.Hosting
{ {
public static class HostBuilderExtensions
{
/// <summary>
/// Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
/// </summary>
public static IHostApplicationBuilder AddTelegrator(this IHostApplicationBuilder builder, TelegramBotHostBuilderSettings settings, IHandlersCollection? handlers = null)
{
if (settings is null)
throw new ArgumentNullException(nameof(settings));
IServiceCollection services = builder.Services;
IConfigurationManager configuration = builder.Configuration;
handlers ??= new HostHandlersCollection(services, settings);
if (handlers is IHostHandlersCollection hostHandlers)
{
foreach (PreBuildingRoutine preBuildRoutine in hostHandlers.PreBuilderRoutines)
{
try
{
// TODO: fix
//preBuildRoutine.Invoke(builder);
Debug.WriteLine("Pre-Building routine was not executed");
}
catch (NotImplementedException)
{
_ = 0xBAD + 0xC0DE;
}
}
}
if (!settings.DisableAutoConfigure)
{
services.Configure<ReceiverOptions>(configuration.GetSection(nameof(ReceiverOptions)));
services.Configure(configuration.GetSection(nameof(TelegramBotClientOptions)), new TelegramBotClientOptionsProxy());
}
else
{
/*
if (null == Services.SingleOrDefault(srvc => srvc.ImplementationType == typeof(IOptions<ReceiverOptions>)))
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'ReceiverOptions' wasn't registered. This configuration is runtime required!");
*/
if (null == services.SingleOrDefault(srvc => srvc.ImplementationType == typeof(IOptions<TelegramBotClientOptions>)))
throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegramBotClientOptions' wasn't registered. This configuration is runtime required!");
}
IOptions<TelegramBotHostBuilderSettings> options = Options.Create(settings);
services.AddSingleton((IOptions<TelegratorOptions>)options);
services.AddTelegramBotHostDefaults();
services.AddSingleton(options);
services.AddSingleton(handlers);
if (handlers is IHandlersManager manager)
{
ServiceDescriptor descriptor = new ServiceDescriptor(typeof(IHandlersProvider), manager);
services.Replace(descriptor);
services.AddSingleton(manager);
}
return builder;
}
}
/// <summary> /// <summary>
/// Contains extensions for <see cref="IServiceCollection"/> /// Contains extensions for <see cref="IServiceCollection"/>
/// Provides method to configure <see cref="ITelegramBotHost"/> /// Provides method to configure <see cref="ITelegramBotHost"/>
@@ -81,15 +154,34 @@ namespace Telegrator.Hosting
/// </summary> /// </summary>
public static class TelegramBotHostExtensions public static class TelegramBotHostExtensions
{ {
/// <summary>
/// Replaces the initialization logic from TelegramBotWebHost constructor.
/// Initializes the bot and logs handlers on application startup.
/// </summary>
public static IHost UseTelegrator(this IHost botHost)
{
ITelegramBotInfo info = botHost.Services.GetRequiredService<ITelegramBotInfo>();
IHandlersCollection handlers = botHost.Services.GetRequiredService<IHandlersCollection>();
ILoggerFactory loggerFactory = botHost.Services.GetRequiredService<ILoggerFactory>();
ILogger logger = loggerFactory.CreateLogger("Telegrator.Hosting.Web.TelegratorHost");
logger.LogInformation("Telegrator Bot .NET Host started");
logger.LogHandlers(handlers);
return botHost;
}
/// <summary> /// <summary>
/// Configures bots available commands depending on what handlers was registered /// Configures bots available commands depending on what handlers was registered
/// </summary> /// </summary>
/// <param name="botHost"></param> /// <param name="botHost"></param>
/// <returns></returns> /// <returns></returns>
public static ITelegramBotHost SetBotCommands(this ITelegramBotHost botHost) public static IHost SetBotCommands(this IHost botHost)
{ {
ITelegramBotClient client = botHost.Services.GetRequiredService<ITelegramBotClient>(); ITelegramBotClient client = botHost.Services.GetRequiredService<ITelegramBotClient>();
IEnumerable<BotCommand> aliases = botHost.UpdateRouter.HandlersProvider.GetBotCommands(); IUpdateRouter router = botHost.Services.GetRequiredService<IUpdateRouter>();
IEnumerable<BotCommand> aliases = router.HandlersProvider.GetBotCommands();
client.SetMyCommands(aliases).Wait(); client.SetMyCommands(aliases).Wait();
return botHost; return botHost;
} }
@@ -98,10 +190,11 @@ namespace Telegrator.Hosting
/// Adds a Microsoft.Extensions.Logging adapter to Alligator using a logger factory. /// Adds a Microsoft.Extensions.Logging adapter to Alligator using a logger factory.
/// </summary> /// </summary>
/// <param name="host"></param> /// <param name="host"></param>
public static ITelegramBotHost AddLoggingAdapter(this ITelegramBotHost host) public static IHost AddLoggingAdapter(this IHost host)
{ {
ILoggerFactory loggerFactory = host.Services.GetRequiredService<ILoggerFactory>(); ILoggerFactory loggerFactory = host.Services.GetRequiredService<ILoggerFactory>();
ILogger logger = loggerFactory.CreateLogger("Telegrator"); ILogger logger = loggerFactory.CreateLogger("Telegrator");
MicrosoftLoggingAdapter adapter = new MicrosoftLoggingAdapter(logger); MicrosoftLoggingAdapter adapter = new MicrosoftLoggingAdapter(logger);
Alligator.AddAdapter(adapter); Alligator.AddAdapter(adapter);
return host; return host;
@@ -129,4 +222,29 @@ namespace Telegrator.Hosting
return routineMethod != null; return routineMethod != null;
} }
} }
public static class LoggerExtensions
{
public static void LogHandlers(this ILogger logger, IHandlersCollection handlers)
{
StringBuilder logBuilder = new StringBuilder("Registered handlers : ");
if (!handlers.Keys.Any())
throw new Exception();
foreach (UpdateType updateType in handlers.Keys)
{
HandlerDescriptorList descriptors = handlers[updateType];
logBuilder.Append("\n\tUpdateType." + updateType + " :");
foreach (HandlerDescriptor descriptor in descriptors.Reverse())
{
logBuilder.AppendFormat("\n\t* {0} - {1}",
descriptor.Indexer.ToString(),
descriptor.ToString());
}
}
logger.LogInformation(logBuilder.ToString());
}
}
} }