diff --git a/Telegrator.slnx b/Telegrator.slnx
index 4e2b0ed..259b22b 100644
--- a/Telegrator.slnx
+++ b/Telegrator.slnx
@@ -4,6 +4,7 @@
+
diff --git a/dev/Telegrator.RoslynGenerators/GlobalSuppressions.cs b/dev/Telegrator.RoslynGenerators/GlobalSuppressions.cs
index 361f387..51b6e82 100644
--- a/dev/Telegrator.RoslynGenerators/GlobalSuppressions.cs
+++ b/dev/Telegrator.RoslynGenerators/GlobalSuppressions.cs
@@ -6,3 +6,4 @@
using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Style", "IDE0090")]
+[assembly: SuppressMessage("Roslynator", "RCS1037")]
diff --git a/dev/Telegrator.RoslynGenerators/ImplicitHandlerBuilderExtensionsGenerator.cs b/dev/Telegrator.RoslynGenerators/ImplicitHandlerBuilderExtensionsGenerator.cs
index 88ff995..9c00486 100644
--- a/dev/Telegrator.RoslynGenerators/ImplicitHandlerBuilderExtensionsGenerator.cs
+++ b/dev/Telegrator.RoslynGenerators/ImplicitHandlerBuilderExtensionsGenerator.cs
@@ -112,7 +112,7 @@ public class ImplicitHandlerBuilderExtensionsGenerator : IIncrementalGenerator
{
try
{
- PrimaryConstructorBaseTypeSyntax primaryConstructor = (PrimaryConstructorBaseTypeSyntax)classDeclaration.BaseList.Types.ElementAt(0);
+ PrimaryConstructorBaseTypeSyntax primaryConstructor = (PrimaryConstructorBaseTypeSyntax)classDeclaration.BaseList.Types[0];
MethodDeclarationSyntax genExtension = GeneratedExtensionsMethod(classDeclaration, classDeclaration.ParameterList, primaryConstructor.ArgumentList, targeter);
extensions.Add(genExtension);
}
@@ -239,7 +239,7 @@ public class ImplicitHandlerBuilderExtensionsGenerator : IIncrementalGenerator
if (targeters.TryGetValue(classDeclaration.Identifier.ValueText, out MethodDeclarationSyntax targeter))
return targeter;
- if (classDeclaration.BaseList != null && targeters.TryGetValue(classDeclaration.BaseList.Types.ElementAt(0).Type.ToString(), out targeter))
+ if (classDeclaration.BaseList != null && targeters.TryGetValue(classDeclaration.BaseList.Types[0].Type.ToString(), out targeter))
return targeter;
return null;
diff --git a/dev/Telegrator.RoslynGenerators/RoslynExtensions/CollectionsExtensions.cs b/dev/Telegrator.RoslynGenerators/RoslynExtensions/CollectionsExtensions.cs
index bac7255..9c63834 100644
--- a/dev/Telegrator.RoslynGenerators/RoslynExtensions/CollectionsExtensions.cs
+++ b/dev/Telegrator.RoslynGenerators/RoslynExtensions/CollectionsExtensions.cs
@@ -1,64 +1,63 @@
-namespace Telegrator.RoslynGenerators.RoslynExtensions
+namespace Telegrator.RoslynGenerators.RoslynExtensions;
+
+public static class CollectionsExtensions
{
- public static class CollectionsExtensions
+ public static IEnumerable Combine(params IEnumerable[] collections)
+ => collections.SelectMany(x => x);
+
+ public static IEnumerable IntersectBy(this IEnumerable first, IEnumerable second, Func selector)
{
- public static IEnumerable Combine(params IEnumerable[] collections)
- => collections.SelectMany(x => x);
-
- public static IEnumerable IntersectBy(this IEnumerable first, IEnumerable second, Func selector)
+ foreach (TSource item in first)
{
- foreach (TSource item in first)
- {
- TValue value = selector(item);
- if (second.Contains(value))
- yield return item;
- }
+ TValue value = selector(item);
+ if (second.Contains(value))
+ yield return item;
}
-
- public static IList UnionAdd(this IList source, IEnumerable toUnion, IEqualityComparer comparer)
- {
- foreach (TValue toUnionValue in toUnion)
- {
- if (!source.Contains(toUnionValue, comparer))
- source.Add(toUnionValue);
- }
-
- return source;
- }
-
- public static void UnionAdd(this ICollection collection, IEnumerable target)
- {
- foreach (TSource item in target)
- {
- if (!collection.Contains(item))
- collection.Add(item);
- }
- }
-
- public static void UnionAdd(this SortedList collection, IEnumerable target)
- {
- foreach (TSource item in target)
- {
- if (!collection.Values.Contains(item))
- collection.Add(item, item);
- }
- }
-
- public static int IndexOf(this IEnumerable source, Func predicate)
- {
- int index = 0;
- foreach (T item in source)
- {
- if (predicate.Invoke(item))
- return index;
-
- index++;
- }
-
- return -1;
- }
-
- public static IEnumerable Repeat(this T item, int times)
- => Enumerable.Range(0, times).Select(_ => item);
}
+
+ public static IList UnionAdd(this IList source, IEnumerable toUnion, IEqualityComparer comparer)
+ {
+ foreach (TValue toUnionValue in toUnion)
+ {
+ if (!source.Contains(toUnionValue, comparer))
+ source.Add(toUnionValue);
+ }
+
+ return source;
+ }
+
+ public static void UnionAdd(this ICollection collection, IEnumerable target)
+ {
+ foreach (TSource item in target)
+ {
+ if (!collection.Contains(item))
+ collection.Add(item);
+ }
+ }
+
+ public static void UnionAdd(this SortedList collection, IEnumerable target)
+ {
+ foreach (TSource item in target)
+ {
+ if (!collection.Values.Contains(item))
+ collection.Add(item, item);
+ }
+ }
+
+ public static int IndexOf(this IEnumerable source, Func predicate)
+ {
+ int index = 0;
+ foreach (T item in source)
+ {
+ if (predicate.Invoke(item))
+ return index;
+
+ index++;
+ }
+
+ return -1;
+ }
+
+ public static IEnumerable Repeat(this T item, int times)
+ => Enumerable.Range(0, times).Select(_ => item);
}
diff --git a/docs/Telegrator.Hosting.Web.xml b/docs/Telegrator.Hosting.Web.xml
index a4e606a..04ff5db 100644
--- a/docs/Telegrator.Hosting.Web.xml
+++ b/docs/Telegrator.Hosting.Web.xml
@@ -4,131 +4,6 @@
Telegrator.Hosting.Web
-
-
- Represents a web hosted telegram bot
-
-
-
-
-
-
-
-
-
-
-
-
-
- Allows consumers to be notified of application lifetime events.
-
-
-
-
- This application's logger
-
-
-
-
-
-
-
- Initializes a new instance of the class.
-
- The proxied instance of host builder.
-
-
-
- Creates new with default services and webhook update receiving scheme
-
-
-
-
-
- Creates new SLIM with default services and webhook update receiving scheme
-
-
-
-
-
- Creates new EMPTY WITHOUT any services or update receiving schemes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Disposes the host.
-
-
-
-
- Disposes the host.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
-
- Initializes a new instance of the class.
-
-
-
-
-
-
- Builds the host.
-
-
-
-
-
-
Configuration options for Telegram bot behavior and execution settings.
@@ -200,20 +75,12 @@
Provides method to configure Telegram Bot WebHost
-
-
- The key used to store the in the builder properties.
-
-
-
-
-
-
+
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
-
+
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
@@ -223,7 +90,12 @@
Replaces TelegramBotWebHostBuilder. Configures DI, options, and handlers.
-
+
+
+ Provides useful methods to adjust Telegram bot Host
+
+
+
Searchs for hosted service inside hosts services
@@ -231,13 +103,13 @@
-
+
Replaces the initialization logic from TelegramBotWebHost constructor.
Initializes the bot and logs handlers on application startup.
-
+
Allows to remap receiving webhook endpoint and map new route to webhost.
@@ -246,17 +118,12 @@
-
+
Registers service with to receive updates using webhook
-
-
- Gets the from the builder properties.
-
-
diff --git a/docs/Telegrator.Hosting.xml b/docs/Telegrator.Hosting.xml
index ec77187..05914c8 100644
--- a/docs/Telegrator.Hosting.xml
+++ b/docs/Telegrator.Hosting.xml
@@ -40,63 +40,6 @@
Represents a hosted telegram bots and services builder that helps manage configuration, logging, lifetime, and more.
-
-
- Represents a hosted telegram bot
-
-
-
-
-
-
-
-
-
-
- This application's logger
-
-
-
-
- Initializes a new instance of the class.
-
- The proxied instance of host builder.
-
-
-
- Creates new with default configuration, services and long-polling update receiving scheme
-
-
-
-
-
- Creates new with default services and long-polling update receiving scheme
-
-
-
-
-
- Creates new EMPTY WITHOUT any services or update receiving schemes
-
-
-
-
-
- Creates new EMPTY WITHOUT any services or update receiving schemes
-
-
-
-
-
-
-
-
-
-
-
- Disposes the host.
-
-
@@ -121,25 +64,19 @@
-
+
Initializes a new instance of the class.
-
+
Initializes a new instance of the class.
-
-
- Builds the host.
-
-
-
@@ -158,7 +95,7 @@
-
+
Service for receiving updates for Hosted telegram bots
@@ -167,7 +104,7 @@
-
+
Service for receiving updates for Hosted telegram bots
@@ -176,24 +113,24 @@
-
+
-
+
-
+
of this router
-
+
-
+
-
+
Default exception handler of this router
@@ -239,12 +176,7 @@
The key used to store the in the builder properties.
-
-
- Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
-
-
-
+
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
@@ -259,6 +191,11 @@
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
+
+
+ Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
+
+
Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
@@ -280,14 +217,14 @@
- Registers default services
+ Registers default services
- Registers service with to receive updates using long polling
+ Registers service with to receive updates using long polling
@@ -307,7 +244,7 @@
- Replaces the initialization logic from TelegramBotWebHost constructor.
+ Replaces the initialization logic from TelegramBotWebHost constructor.
Initializes the bot and logs handlers on application startup.
diff --git a/docs/Telegrator.xml b/docs/Telegrator.xml
index 71bbd19..d43eb31 100644
--- a/docs/Telegrator.xml
+++ b/docs/Telegrator.xml
@@ -6027,6 +6027,9 @@
Manages the distribution of updates between regular handlers and awaiting handlers.
+
+
+
@@ -6036,9 +6039,6 @@
-
-
-
@@ -6377,14 +6377,9 @@
Represents handler results, allowing to communicate with router and control aspect execution
-
+
- Is result positive
-
-
-
-
- Should router search for next matching handler
+ Tell router to stop describing
@@ -6449,6 +6444,14 @@
+
+
+ Remove all values and returns collection without nullable type.
+
+
+
+
+
Enumerates objects in a and executes an on each one
@@ -6558,7 +6561,7 @@
-
+
Checks if is an implementation of class or its descendants
@@ -6802,7 +6805,7 @@
Initializes the update router and begins polling for updates.
Optional receiver options for configuring update polling.
- The cancellation token to stop receiving updates.
+ The cancellation token to stop receiving updates.
@@ -7113,6 +7116,14 @@
Provides convenient methods for creating implicit handlers.
+
+
+ Collects all handlers from current app domain.
+ Scans for handlers exported by analyzer into class `Telegrator.Analyzers.AnalyzerExport` in each assembly and registers them to the collection.
+
+
+
+
Collects all public handlers from the current app domain.
diff --git a/src/Telegrator.Analyzers/DeveloperHelperAnalyzer.cs b/src/Telegrator.Analyzers/DeveloperHelperAnalyzer.cs
index 4e84bcc..0e457e3 100644
--- a/src/Telegrator.Analyzers/DeveloperHelperAnalyzer.cs
+++ b/src/Telegrator.Analyzers/DeveloperHelperAnalyzer.cs
@@ -10,6 +10,8 @@ namespace Telegrator.Analyzers;
[Generator(LanguageNames.CSharp)]
public class DeveloperHelperAnalyzer : IIncrementalGenerator
{
+ internal record class HandlerDeclarationModel(string ClassName, string NamespaceName, string? AttributeName, string? BaseClassName, Location Location);
+
private static readonly DiagnosticDescriptor MissingBaseClassWarning = new(
id: "TLG101",
title: "Missing handlers base class",
@@ -131,9 +133,8 @@ public class DeveloperHelperAnalyzer : IIncrementalGenerator
private static FieldDeclarationSyntax GenerateTypeField(HandlerDeclarationModel handler)
{
- string fullTypeName = handler.Namespace == "Global"
- ? handler.ClassName
- : $"{handler.Namespace}.{handler.ClassName}";
+ string fullTypeName = handler.NamespaceName == "Global"
+ ? handler.ClassName : $"{handler.NamespaceName}.{handler.ClassName}";
TypeOfExpressionSyntax typeofExpression = SyntaxFactory.TypeOfExpression(SyntaxFactory.ParseTypeName(fullTypeName));
VariableDeclaratorSyntax variableDeclarator = SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier($"{handler.ClassName}Type"))
@@ -149,15 +150,6 @@ public class DeveloperHelperAnalyzer : IIncrementalGenerator
}
}
-internal class HandlerDeclarationModel(string className, string namespaceName, string? attributeName, string? baseClassName, Location location)
-{
- public readonly string ClassName = className;
- public readonly string Namespace = namespaceName;
- public readonly string? AttributeName = attributeName;
- public readonly string? BaseClassName = baseClassName;
- public readonly Location Location = location;
-}
-
internal static class DeveloperHelperAnalyzerExtensions
{
private static readonly string[] HandlersNames =
diff --git a/src/Telegrator.Analyzers/GeneratedKeyboardMarkupGenerator.cs b/src/Telegrator.Analyzers/KeyboardMarkupGenerator.cs
similarity index 95%
rename from src/Telegrator.Analyzers/GeneratedKeyboardMarkupGenerator.cs
rename to src/Telegrator.Analyzers/KeyboardMarkupGenerator.cs
index 655fdb2..70d4345 100644
--- a/src/Telegrator.Analyzers/GeneratedKeyboardMarkupGenerator.cs
+++ b/src/Telegrator.Analyzers/KeyboardMarkupGenerator.cs
@@ -8,8 +8,12 @@ using System.Text;
namespace Telegrator.Analyzers;
[Generator(LanguageNames.CSharp)]
-public class GeneratedKeyboardMarkupGenerator : IIncrementalGenerator
+public class KeyboardMarkupGenerator : IIncrementalGenerator
{
+ // Records
+ private record class GeneratedMarkupMethodModel(MethodDeclarationSyntax OriginalMethod, FieldDeclarationSyntax GeneratedField, MethodDeclarationSyntax GeneratedMethod);
+ private record class GeneratedMarkupPropertyModel(PropertyDeclarationSyntax OriginalProperty, PropertyDeclarationSyntax GeneratedProperty);
+
// Return types
private const string InlineReturnType = "InlineKeyboardMarkup";
private const string ReplyReturnType = "ReplyKeyboardMarkup";
@@ -459,30 +463,4 @@ public class GeneratedKeyboardMarkupGenerator : IIncrementalGenerator
SyntaxFactory.IdentifierName(className),
SyntaxFactory.IdentifierName(methodName));
}
-
- private class GeneratedMarkupMethodModel
- {
- public MethodDeclarationSyntax OriginalMethod { get; }
- public FieldDeclarationSyntax GeneratedField { get; }
- public MethodDeclarationSyntax GeneratedMethod { get; }
-
- public GeneratedMarkupMethodModel(MethodDeclarationSyntax originalMethod, FieldDeclarationSyntax generatedField, MethodDeclarationSyntax generatedMethod)
- {
- OriginalMethod = originalMethod;
- GeneratedField = generatedField;
- GeneratedMethod = generatedMethod;
- }
- }
-
- private class GeneratedMarkupPropertyModel
- {
- public PropertyDeclarationSyntax OriginalProperty { get; }
- public PropertyDeclarationSyntax GeneratedProperty { get; }
-
- public GeneratedMarkupPropertyModel(PropertyDeclarationSyntax originalProperty, PropertyDeclarationSyntax generatedProperty)
- {
- OriginalProperty = originalProperty;
- GeneratedProperty = generatedProperty;
- }
- }
}
\ No newline at end of file
diff --git a/src/Telegrator.Analyzers/RoslynExtensions/Exceptions.cs b/src/Telegrator.Analyzers/RoslynExtensions/Exceptions.cs
index 7124a8b..a958cf0 100644
--- a/src/Telegrator.Analyzers/RoslynExtensions/Exceptions.cs
+++ b/src/Telegrator.Analyzers/RoslynExtensions/Exceptions.cs
@@ -1,7 +1,7 @@
namespace Telegrator.Analyzers.RoslynExtensions;
-public class TargteterNotFoundException() : Exception() { }
-
-public class BaseClassTypeNotFoundException() : Exception() { }
-
-public class AncestorNotFoundException : Exception { }
+#pragma warning disable RCS1194 // Implement exception constructors
+public class TargteterNotFoundException() : Exception();
+public class BaseClassTypeNotFoundException() : Exception();
+public class AncestorNotFoundException() : Exception();
+#pragma warning restore RCS1194 // Implement exception constructors
diff --git a/src/Telegrator.Hosting.Web/GlobalSuppressions.cs b/src/Telegrator.Hosting.Web/GlobalSuppressions.cs
index 691de9c..a017ac2 100644
--- a/src/Telegrator.Hosting.Web/GlobalSuppressions.cs
+++ b/src/Telegrator.Hosting.Web/GlobalSuppressions.cs
@@ -10,3 +10,5 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Usage", "CA2254")]
[assembly: SuppressMessage("Maintainability", "CA1510")]
[assembly: SuppressMessage("Style", "IDE0270")]
+[assembly: SuppressMessage("Roslynator", "RCS1037")]
+[assembly: SuppressMessage("Roslynator", "RCS1224")]
diff --git a/src/Telegrator.Hosting.Web/Hosting.Web/TelegramBotWebHost.cs b/src/Telegrator.Hosting.Web/Hosting.Web/TelegramBotWebHost.cs
deleted file mode 100644
index 38b96c4..0000000
--- a/src/Telegrator.Hosting.Web/Hosting.Web/TelegramBotWebHost.cs
+++ /dev/null
@@ -1,159 +0,0 @@
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Http.Features;
-using Microsoft.AspNetCore.Routing;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Telegrator.Core;
-
-namespace Telegrator.Hosting.Web;
-
-///
-/// Represents a web hosted telegram bot
-///
-public class TelegramBotWebHost : IHost, IApplicationBuilder, IEndpointRouteBuilder, IAsyncDisposable
-{
- private readonly WebApplication _innerApp;
- private readonly IUpdateRouter _updateRouter;
- private readonly ILogger _logger;
-
- private bool _disposed;
-
- ///
- public IServiceProvider Services => _innerApp.Services;
-
- ///
- public IUpdateRouter UpdateRouter => _updateRouter;
-
- ///
- public ICollection DataSources => ((IEndpointRouteBuilder)_innerApp).DataSources;
-
- ///
- /// Allows consumers to be notified of application lifetime events.
- ///
- public IHostApplicationLifetime Lifetime => _innerApp.Lifetime;
-
- ///
- /// This application's logger
- ///
- public ILogger Logger => _logger;
-
- ///
- public IDictionary Properties => ((IApplicationBuilder)_innerApp).Properties;
-
- // Private interface fields
- IServiceProvider IEndpointRouteBuilder.ServiceProvider => Services;
- IServiceProvider IApplicationBuilder.ApplicationServices { get => Services; set => throw new NotImplementedException(); }
- IFeatureCollection IApplicationBuilder.ServerFeatures => ((IApplicationBuilder)_innerApp).ServerFeatures;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The proxied instance of host builder.
- public TelegramBotWebHost(WebApplicationBuilder webApplicationBuilder)
- {
- // Building proxy application
- _innerApp = webApplicationBuilder.Build();
-
- // Reruesting services for this host
- _updateRouter = Services.GetRequiredService();
- _logger = Services.GetRequiredService>();
- }
-
- ///
- /// Creates new with default services and webhook update receiving scheme
- ///
- ///
- public static TelegramBotWebHostBuilder CreateBuilder(WebApplicationOptions? settings)
- {
- ArgumentNullException.ThrowIfNull(settings, nameof(settings));
- WebApplicationBuilder innerApp = WebApplication.CreateBuilder(settings);
- TelegramBotWebHostBuilder builder = new TelegramBotWebHostBuilder(innerApp);
- builder.AddTelegratorWeb();
- return builder;
- }
-
- ///
- /// Creates new SLIM with default services and webhook update receiving scheme
- ///
- ///
- public static TelegramBotWebHostBuilder CreateSlimBuilder(WebApplicationOptions? settings)
- {
- ArgumentNullException.ThrowIfNull(settings, nameof(settings));
- WebApplicationBuilder innerApp = WebApplication.CreateSlimBuilder(settings);
- TelegramBotWebHostBuilder builder = new TelegramBotWebHostBuilder(innerApp);
- builder.AddTelegratorWeb();
- return builder;
- }
-
- ///
- /// Creates new EMPTY WITHOUT any services or update receiving schemes
- ///
- ///
- public static TelegramBotWebHostBuilder CreateEmptyBuilder(WebApplicationOptions? settings)
- {
- ArgumentNullException.ThrowIfNull(settings, nameof(settings));
- WebApplicationBuilder innerApp = WebApplication.CreateEmptyBuilder(settings);
- TelegramBotWebHostBuilder builder = new TelegramBotWebHostBuilder(innerApp);
- builder.AddTelegratorWeb();
- return builder;
- }
-
- ///
- public async Task StartAsync(CancellationToken cancellationToken = default)
- {
- await _innerApp.StartAsync(cancellationToken);
- }
-
- ///
- public async Task StopAsync(CancellationToken cancellationToken = default)
- {
- await _innerApp.StopAsync(cancellationToken);
- }
-
- ///
- public IApplicationBuilder CreateApplicationBuilder()
- => ((IEndpointRouteBuilder)_innerApp).CreateApplicationBuilder();
-
- ///
- public IApplicationBuilder Use(Func middleware)
- => _innerApp.Use(middleware);
-
- ///
- public IApplicationBuilder New()
- => ((IApplicationBuilder)_innerApp).New();
-
- ///
- public RequestDelegate Build()
- => ((IApplicationBuilder)_innerApp).Build();
-
- ///
- /// Disposes the host.
- ///
- public async ValueTask DisposeAsync()
- {
- if (_disposed)
- return;
-
- await _innerApp.DisposeAsync();
-
- GC.SuppressFinalize(this);
- _disposed = true;
- }
-
- ///
- /// Disposes the host.
- ///
- public void Dispose()
- {
- if (_disposed)
- return;
-
- ValueTask disposeTask = _innerApp.DisposeAsync();
- disposeTask.AsTask().Wait();
-
- GC.SuppressFinalize(this);
- _disposed = true;
- }
-}
diff --git a/src/Telegrator.Hosting.Web/Hosting.Web/TelegramBotWebHostBuilder.cs b/src/Telegrator.Hosting.Web/Hosting.Web/TelegramBotWebHostBuilder.cs
deleted file mode 100644
index fb813ba..0000000
--- a/src/Telegrator.Hosting.Web/Hosting.Web/TelegramBotWebHostBuilder.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using Microsoft.AspNetCore.Builder;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Diagnostics.Metrics;
-using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using Telegrator.Core;
-
-#pragma warning disable IDE0001
-namespace Telegrator.Hosting.Web;
-
-///
-public class TelegramBotWebHostBuilder : ITelegramBotHostBuilder
-{
- private readonly WebApplicationBuilder _innerBuilder;
- internal IHandlersCollection _handlers = null!;
-
- ///
- public IHandlersCollection Handlers => _handlers;
-
- ///
- public IConfigurationManager Configuration => _innerBuilder.Configuration;
-
- ///
- public ILoggingBuilder Logging => _innerBuilder.Logging;
-
- ///
- public IServiceCollection Services => _innerBuilder.Services;
-
- ///
- public IHostEnvironment Environment => _innerBuilder.Environment;
-
- ///
- public IDictionary
///
- public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder)
+ public TelegramBotHostBuilder(IHostApplicationBuilder hostApplicationBuilder)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
}
@@ -49,23 +49,12 @@ public class TelegramBotHostBuilder : ITelegramBotHostBuilder
///
///
///
- public TelegramBotHostBuilder(HostApplicationBuilder hostApplicationBuilder, IHandlersCollection handlers)
+ public TelegramBotHostBuilder(IHostApplicationBuilder hostApplicationBuilder, IHandlersCollection handlers)
{
_innerBuilder = hostApplicationBuilder ?? throw new ArgumentNullException(nameof(hostApplicationBuilder));
_handlers = handlers ?? throw new ArgumentNullException(nameof(handlers));
}
- ///
- /// Builds the host.
- ///
- ///
- public TelegramBotHost Build()
- {
- TelegramBotHost host = new TelegramBotHost(_innerBuilder);
- host.UseTelegrator();
- return host;
- }
-
///
public void ConfigureContainer(IServiceProviderFactory factory, Action? configure = null) where TContainerBuilder : notnull
{
diff --git a/src/Telegrator.Hosting/Polling/HostUpdateRouter.cs b/src/Telegrator.Hosting/Mediation/HostUpdateRouter.cs
similarity index 97%
rename from src/Telegrator.Hosting/Polling/HostUpdateRouter.cs
rename to src/Telegrator.Hosting/Mediation/HostUpdateRouter.cs
index a4cbcca..d8c2e61 100644
--- a/src/Telegrator.Hosting/Polling/HostUpdateRouter.cs
+++ b/src/Telegrator.Hosting/Mediation/HostUpdateRouter.cs
@@ -5,9 +5,8 @@ using Telegram.Bot.Polling;
using Telegram.Bot.Types;
using Telegrator.Core;
using Telegrator.Core.States;
-using Telegrator.Mediation;
-namespace Telegrator.Polling;
+namespace Telegrator.Mediation;
///
public class HostUpdateRouter : UpdateRouter
diff --git a/src/Telegrator.Hosting/Polling/HostedUpdateReceiver.cs b/src/Telegrator.Hosting/Mediation/HostedUpdateReceiver.cs
similarity index 90%
rename from src/Telegrator.Hosting/Polling/HostedUpdateReceiver.cs
rename to src/Telegrator.Hosting/Mediation/HostedUpdateReceiver.cs
index 06489b8..89d8f02 100644
--- a/src/Telegrator.Hosting/Polling/HostedUpdateReceiver.cs
+++ b/src/Telegrator.Hosting/Mediation/HostedUpdateReceiver.cs
@@ -4,9 +4,8 @@ using Microsoft.Extensions.Options;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegrator.Core;
-using Telegrator.Mediation;
-namespace Telegrator.Polling;
+namespace Telegrator.Mediation;
///
/// Service for receiving updates for Hosted telegram bots
@@ -26,7 +25,8 @@ public class HostedUpdateReceiver(ITelegramBotClient botClient, IUpdateRouter up
logger.LogInformation("Starting receiving updates via long-polling");
_receiverOptions.AllowedUpdates = _updateRouter.HandlersProvider.AllowedTypes.ToArray();
- botClient.DeleteWebhook(options.Value.DropPendingUpdates).Wait();
+ botClient.DeleteWebhook(options.Value.DropPendingUpdates, cancellationToken: stoppingToken)
+ .ConfigureAwait(false).GetAwaiter().GetResult();
DefaultUpdateReceiver updateReceiver = new DefaultUpdateReceiver(botClient, _receiverOptions);
await updateReceiver.ReceiveAsync(_updateRouter, stoppingToken).ConfigureAwait(false);
diff --git a/src/Telegrator.Hosting/Providers/HostHandlersCollection.cs b/src/Telegrator.Hosting/Providers/HostHandlersCollection.cs
index 8628050..4584fcf 100644
--- a/src/Telegrator.Hosting/Providers/HostHandlersCollection.cs
+++ b/src/Telegrator.Hosting/Providers/HostHandlersCollection.cs
@@ -17,41 +17,60 @@ public class HostHandlersCollection(IServiceCollection hostServiceColletion, Tel
{
switch (descriptor.Type)
{
+ default:
+ throw new Exception("Unknown descriptor type");
+
case DescriptorType.General:
{
if (descriptor.InstanceFactory != null)
+ {
Services.AddScoped(descriptor.HandlerType, _ => descriptor.InstanceFactory.Invoke());
- else
- Services.AddScoped(descriptor.HandlerType);
+ break;
+ }
+ Services.AddScoped(descriptor.HandlerType);
break;
}
case DescriptorType.Keyed:
{
if (descriptor.InstanceFactory != null)
+ {
Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey, (_, _) => descriptor.InstanceFactory.Invoke());
- else
- Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey);
+ break;
+ }
+ Services.AddKeyedScoped(descriptor.HandlerType, descriptor.ServiceKey);
break;
}
case DescriptorType.Singleton:
{
- Services.AddSingleton(descriptor.HandlerType, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null
- ? descriptor.InstanceFactory.Invoke()
- : throw new Exception()));
+ if (descriptor.SingletonInstance != null)
+ {
+ Services.AddSingleton(descriptor.HandlerType, descriptor.SingletonInstance);
+ break;
+ }
+ if (descriptor.InstanceFactory == null)
+ throw new InvalidOperationException("Singleton handler descriptor without singleton instance should implement `InstanceFactory`");
+
+ Services.AddSingleton(descriptor.HandlerType, descriptor.InstanceFactory.Invoke());
break;
}
case DescriptorType.Implicit:
{
- Services.AddKeyedSingleton(descriptor.HandlerType, descriptor.ServiceKey, descriptor.SingletonInstance ?? (descriptor.InstanceFactory != null
- ? descriptor.InstanceFactory.Invoke()
- : throw new Exception()));
-
+ if (descriptor.SingletonInstance != null)
+ {
+ Services.AddKeyedSingleton(descriptor.HandlerType, descriptor.ServiceKey, descriptor.SingletonInstance);
+ break;
+ }
+
+ if (descriptor.InstanceFactory == null)
+ throw new InvalidOperationException("Implicit handler descriptor without singleton instance should implement `InstanceFactory`");
+
+ Services.AddKeyedSingleton(descriptor.HandlerType, descriptor.ServiceKey, descriptor.InstanceFactory.Invoke());
break;
}
}
diff --git a/src/Telegrator.Hosting/TypesExtensions.cs b/src/Telegrator.Hosting/TypesExtensions.cs
index 0e5294a..c998be2 100644
--- a/src/Telegrator.Hosting/TypesExtensions.cs
+++ b/src/Telegrator.Hosting/TypesExtensions.cs
@@ -15,7 +15,7 @@ using Telegrator.Core.Descriptors;
using Telegrator.Core.States;
using Telegrator.Hosting;
using Telegrator.Logging;
-using Telegrator.Polling;
+using Telegrator.Mediation;
using Telegrator.Providers;
using Telegrator.States;
@@ -34,20 +34,7 @@ public static class HostBuilderExtensions
///
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
///
- public static ITelegramBotHostBuilder AddTelegrator(this ITelegramBotHostBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action? action = null)
- {
- AddTelegratorInternal(builder.Services, builder.Configuration, builder.Properties, ref handlers, options);
- if (builder is TelegramBotHostBuilder telegramBotHostBuilder)
- telegramBotHostBuilder._handlers = handlers;
-
- action?.Invoke(builder);
- return builder;
- }
-
- ///
- /// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
- ///
- public static IHostApplicationBuilder AddTelegrator(this HostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action? action = null)
+ public static IHostApplicationBuilder AddTelegrator(this IHostApplicationBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action? action = null)
{
AddTelegratorInternal(builder.Services, builder.Configuration, ((IHostApplicationBuilder)builder).Properties, ref handlers, options);
action?.Invoke(new TelegramBotHostBuilder(builder, handlers));
@@ -72,6 +59,16 @@ public static class HostBuilderExtensions
return builder;
}
+ ///
+ /// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
+ ///
+ public static IHostBuilder AddTelegrator(this IHostBuilder builder, TelegratorOptions? options = null, IHandlersCollection? handlers = null, Action? action = null)
+ {
+ builder.ConfigureServices((ctx, sp) => AddTelegratorInternal(sp, ctx.Configuration, builder.Properties, ref handlers, options));
+ action?.Invoke(handlers!); // AddTelegratorInternal initializes `handlers`
+ return builder;
+ }
+
///
/// Replaces TelegramBotHostBuilder. Configures DI, options, and handlers.
///
@@ -81,7 +78,7 @@ public static class HostBuilderExtensions
{
options = configuration.GetSection(nameof(TelegratorOptions)).Get();
if (options == null)
- throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegratorOptions' wasn't registered. This configuration is runtime required!");
+ throw new MissingMemberException("Auto configuration disabled, yet no options of type 'TelegratorOptions' was registered. This configuration is runtime required!");
}
CancellationTokenSource globallCancell = new CancellationTokenSource();
@@ -103,11 +100,11 @@ public static class HostBuilderExtensions
services.AddSingleton(handlers);
properties.Add(HandlersCollectionPropertyKey, handlers);
- if (!services.Any(srvc => srvc.ImplementationType == typeof(IOptions)))
+ if (!services.Any(srvc => srvc.ServiceType == typeof(IOptions)))
{
ReceiverOptions? receiverOptions = configuration.GetSection(nameof(ReceiverOptions)).Get();
if (receiverOptions == null)
- throw new MissingMemberException("Auto configuration disabled, yet no options of type 'ReceiverOptions' wasn't registered. This configuration is runtime required!");
+ throw new MissingMemberException("Auto configuration disabled, yet no options of type 'ReceiverOptions' was registered. This configuration is runtime required!");
services.AddSingleton(Options.Create(receiverOptions));
}
@@ -132,6 +129,18 @@ public static class HostBuilderExtensions
///
public static class ServicesCollectionExtensions
{
+ public static IServiceCollection ConfigureTelegram(this IServiceCollection services, TelegramBotClientOptions options)
+ {
+ services.AddSingleton(Options.Create(options));
+ return services;
+ }
+
+ public static IServiceCollection ConfigureReceiver(this IServiceCollection services, ReceiverOptions options)
+ {
+ services.AddSingleton(Options.Create(options));
+ return services;
+ }
+
///
/// Registers service
///
@@ -145,7 +154,7 @@ public static class ServicesCollectionExtensions
}
///
- /// Registers default services
+ /// Registers default services
///
///
///
@@ -188,7 +197,7 @@ public static class ServicesCollectionExtensions
public static class TelegramBotHostExtensions
{
///
- /// Replaces the initialization logic from TelegramBotWebHost constructor.
+ /// Replaces the initialization logic from TelegramBotWebHost constructor.
/// Initializes the bot and logs handlers on application startup.
///
public static IHost UseTelegrator(this IHost botHost)
@@ -200,11 +209,14 @@ public static class TelegramBotHostExtensions
if (logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Information))
{
- logger.LogInformation("Telegrator Bot .NET Host started");
+ logger.LogInformation("Telegrator Bot Host started (Generic Host)");
+ logger.LogInformation("Receiving mode : LONG-POLLING");
logger.LogInformation("Telegram Bot : {firstname}, @{usrname}, id:{id},", info.User.FirstName ?? "[NULL]", info.User.Username ?? "[NULL]", info.User.Id);
logger.LogHandlers(handlers);
}
+ botHost.AddLoggingAdapter();
+ botHost.SetBotCommands();
return botHost;
}
@@ -219,7 +231,12 @@ public static class TelegramBotHostExtensions
IUpdateRouter router = botHost.Services.GetRequiredService();
IEnumerable aliases = router.HandlersProvider.GetBotCommands();
- client.SetMyCommands(aliases).Wait();
+ if (aliases.Any())
+ {
+ client.SetMyCommands(aliases)
+ .ConfigureAwait(false).GetAwaiter().GetResult();
+ }
+
return botHost;
}
@@ -255,7 +272,7 @@ public static class LoggerExtensions
StringBuilder logBuilder = new StringBuilder("Registered handlers : ");
if (!handlers.Keys.Any())
- throw new Exception();
+ throw new Exception("No update types were registered");
foreach (UpdateType updateType in handlers.Keys)
{
diff --git a/src/Telegrator/Core/Handlers/UpdateHandlerBase.cs b/src/Telegrator/Core/Handlers/UpdateHandlerBase.cs
index 850826e..9997296 100644
--- a/src/Telegrator/Core/Handlers/UpdateHandlerBase.cs
+++ b/src/Telegrator/Core/Handlers/UpdateHandlerBase.cs
@@ -56,7 +56,7 @@ public abstract class UpdateHandlerBase(UpdateType handlingUpdateType) : IUpdate
.ExecutePre(this, container, cancellationToken)
.ConfigureAwait(false);
- if (!preResult.Positive)
+ if (!preResult.InterruptRouter)
return preResult;
}
catch (NotImplementedException)
@@ -69,7 +69,7 @@ public abstract class UpdateHandlerBase(UpdateType handlingUpdateType) : IUpdate
{
// Executing handler
Result execResult = await ExecuteInternal(container, cancellationToken).ConfigureAwait(false);
- if (!execResult.Positive)
+ if (!execResult.InterruptRouter)
return execResult;
}
catch (NotImplementedException)
@@ -86,7 +86,7 @@ public abstract class UpdateHandlerBase(UpdateType handlingUpdateType) : IUpdate
.ExecutePost(this, container, cancellationToken)
.ConfigureAwait(false);
- if (!postResult.Positive)
+ if (!postResult.InterruptRouter)
return postResult;
}
}
diff --git a/src/Telegrator/Mediation/UpdateRouter.cs b/src/Telegrator/Mediation/UpdateRouter.cs
index 9bbd876..7be110c 100644
--- a/src/Telegrator/Mediation/UpdateRouter.cs
+++ b/src/Telegrator/Mediation/UpdateRouter.cs
@@ -19,27 +19,22 @@ namespace Telegrator.Mediation;
///
public class UpdateRouter : IUpdateRouter
{
- private readonly TelegratorOptions _options;
- private readonly IHandlersProvider _handlersProvider;
- private readonly IAwaitingProvider _awaitingProvider;
- private readonly IStateStorage _stateStorage;
- private readonly IUpdateHandlersPool _HandlersPool;
private readonly ITelegramBotInfo _botInfo;
///
- public IHandlersProvider HandlersProvider => _handlersProvider;
+ public TelegratorOptions Options { get; }
///
- public IAwaitingProvider AwaitingProvider => _awaitingProvider;
+ public IHandlersProvider HandlersProvider { get; }
///
- public IStateStorage StateStorage => _stateStorage;
+ public IAwaitingProvider AwaitingProvider { get; }
///
- public TelegratorOptions Options => _options;
+ public IStateStorage StateStorage { get; }
///
- public IUpdateHandlersPool HandlersPool => _HandlersPool;
+ public IUpdateHandlersPool HandlersPool { get; }
///
public IRouterExceptionHandler? ExceptionHandler { get; set; }
@@ -57,11 +52,11 @@ public class UpdateRouter : IUpdateRouter
///
public UpdateRouter(IHandlersProvider handlersProvider, IAwaitingProvider awaitingProvider, IStateStorage stateStorage, TelegratorOptions options, ITelegramBotInfo botInfo)
{
- _options = options;
- _handlersProvider = handlersProvider;
- _awaitingProvider = awaitingProvider;
- _stateStorage = stateStorage;
- _HandlersPool = new UpdateHandlersPool(this, _options, _options.GlobalCancellationToken);
+ Options = options;
+ HandlersProvider = handlersProvider;
+ AwaitingProvider = awaitingProvider;
+ StateStorage = stateStorage;
+ HandlersPool = new UpdateHandlersPool(this, Options, Options.GlobalCancellationToken);
_botInfo = botInfo;
}
@@ -116,7 +111,7 @@ public class UpdateRouter : IUpdateRouter
if (lastResult == null)
break; // Smth went horribly wrong, better to stop routing
- if (lastResult != null && !lastResult.RouteNext)
+ if (lastResult.InterruptRouter)
break;
TelegratorLogging.LogTrace("Handler '{0}' requested route continuation (Update {1})", handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id);
@@ -146,7 +141,7 @@ public class UpdateRouter : IUpdateRouter
if (lastResult == null)
break; // Smth went horribly wrong, better to stop routing
- if (lastResult != null && !lastResult.RouteNext)
+ if (lastResult.InterruptRouter)
break;
TelegratorLogging.LogTrace("Handler '{0}' requested route continuation (Update {1})", handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id);
@@ -248,17 +243,13 @@ public class UpdateRouter : IUpdateRouter
{
FiltersFallbackReport report = new FiltersFallbackReport(descriptor, filterContext);
Result filtersResult = descriptor.Filters.Validate(filterContext, descriptor.FormReport, ref report);
+
+ if (filtersResult.InterruptRouter)
+ return null;
- if (filtersResult.RouteNext)
- {
- Result fallbackResult = handlerInstance.FiltersFallback(report, client, cancellationToken).Result;
- breakRouting = !fallbackResult.RouteNext;
- return null;
- }
- else if (!filtersResult.Positive)
- {
- return null;
- }
+ Result fallbackResult = handlerInstance.FiltersFallback(report, client, cancellationToken).Result;
+ breakRouting = fallbackResult.InterruptRouter;
+ return null;
}
return new DescribedHandlerDescriptor(descriptor, this, AwaitingProvider, StateStorage, client, handlerInstance, filterContext, descriptor.DisplayString);
@@ -307,6 +298,4 @@ public class UpdateRouter : IUpdateRouter
TelegratorLogging.LogTrace(sb.ToString());
}
-
- private class BreakDescribingException : Exception { }
}
diff --git a/src/Telegrator/Result.cs b/src/Telegrator/Result.cs
index ddadd12..6276ab0 100644
--- a/src/Telegrator/Result.cs
+++ b/src/Telegrator/Result.cs
@@ -10,29 +10,23 @@ namespace Telegrator;
///
public sealed class Result
{
- private static readonly Result ok = new Result(true, false, null);
- private static readonly Result fault = new Result(false, false, null);
- private static readonly Result next = new Result(true, true, null);
+ private static readonly Result ok = new Result(true, null);
+ private static readonly Result fault = new Result(true, null);
+ private static readonly Result next = new Result(false, null);
///
- /// Is result positive
+ /// Tell router to stop describing
///
- public bool Positive { get; }
-
- ///
- /// Should router search for next matching handler
- ///
- public bool RouteNext { get; }
+ public bool InterruptRouter { get; }
///
/// Exact type that router should search
///
public Type? NextType { get; }
- internal Result(bool positive, bool routeNext, Type? nextType)
+ internal Result(bool interruptRouter, Type? nextType)
{
- Positive = positive;
- RouteNext = routeNext;
+ InterruptRouter = interruptRouter;
NextType = nextType;
}
@@ -79,5 +73,5 @@ public sealed class Result
///
///
public static Result Next()
- => new Result(true, true, typeof(T));
+ => new Result(false, typeof(T));
}
diff --git a/src/Telegrator/SimpleTypesExtensions.cs b/src/Telegrator/SimpleTypesExtensions.cs
index 98aeea9..0c00229 100644
--- a/src/Telegrator/SimpleTypesExtensions.cs
+++ b/src/Telegrator/SimpleTypesExtensions.cs
@@ -26,6 +26,21 @@ public static partial class ColletionsExtensions
return new ReadOnlyDictionary(dictionary);
}
+ ///
+ /// Remove all values and returns collection without nullable type.
+ ///
+ ///
+ ///
+ ///
+ public static IEnumerable Squeeze(this IEnumerable source)
+ {
+ foreach (T? item in source)
+ {
+ if (item is not null)
+ yield return item;
+ }
+ }
+
///
/// Enumerates objects in a and executes an on each one
///
@@ -188,7 +203,7 @@ public static partial class ReflectionExtensions
///
///
///
- public static bool IsHandlerRealization(this Type type)
+ public static bool IsHandlerImplementation(this Type type)
=> !type.IsAbstract && type != typeof(UpdateHandlerBase) && typeof(UpdateHandlerBase).IsAssignableFrom(type);
///
@@ -260,6 +275,7 @@ public static partial class StringExtensions
{
char[] chars = target.ToCharArray();
int index = chars.IndexOf(char.IsLetter);
+
chars[index] = char.ToUpper(chars[index]);
return new string(chars);
}
@@ -273,6 +289,7 @@ public static partial class StringExtensions
{
char[] chars = target.ToCharArray();
int index = chars.IndexOf(char.IsLetter);
+
chars[index] = char.ToLower(chars[index]);
return new string(chars);
}
diff --git a/src/Telegrator/TelegratorClient.cs b/src/Telegrator/TelegratorClient.cs
index 05d6f1f..ec16e3f 100644
--- a/src/Telegrator/TelegratorClient.cs
+++ b/src/Telegrator/TelegratorClient.cs
@@ -29,7 +29,7 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
public ITelegramBotInfo BotInfo { get; private set; }
///
- public IUpdateRouter UpdateRouter { get => updateRouter ?? throw new Exception(); }
+ public IUpdateRouter UpdateRouter => updateRouter ?? throw new InvalidOperationException("Router's not created yet. Invoke `StartReceiving` to initialize this property.");
///
/// Initializes a new instance of the class with a bot token.
@@ -68,11 +68,11 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
/// Initializes the update router and begins polling for updates.
///
/// Optional receiver options for configuring update polling.
- /// The cancellation token to stop receiving updates.
- public void StartReceiving(ReceiverOptions? receiverOptions = null, CancellationToken cancellationToken = default)
+ /// The cancellation token to stop receiving updates.
+ public void StartReceiving(ReceiverOptions? receiverOptions = null, CancellationToken globalCancellationToken = default)
{
if (Options.GlobalCancellationToken == CancellationToken.None)
- Options.GlobalCancellationToken = cancellationToken;
+ Options.GlobalCancellationToken = globalCancellationToken;
HandlersProvider handlerProvider = new HandlersProvider(Handlers, Options);
AwaitingProvider awaitingProvider = new AwaitingProvider(Options);
@@ -82,8 +82,7 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
// Log startup
TelegratorLogging.LogInformation($"Telegrator bot starting up - BotId: {BotInfo.User.Id}, Username: {BotInfo.User.Username}, MaxParallelHandlers: {Options.MaximumParallelWorkingHandlers ?? -1}");
-
- StartReceivingInternal(receiverOptions, cancellationToken);
+ StartReceivingInternal(receiverOptions, globalCancellationToken);
}
///
@@ -115,6 +114,4 @@ public class TelegratorClient : TelegramBotClient, ITelegratorBot, ICollectingPr
TelegratorLogging.LogInformation("Telegrator bot stopped (cancelled)");
}
}
-
-
}
diff --git a/src/Telegrator/TypesExtensions.cs b/src/Telegrator/TypesExtensions.cs
index b6e2904..93db750 100644
--- a/src/Telegrator/TypesExtensions.cs
+++ b/src/Telegrator/TypesExtensions.cs
@@ -412,6 +412,26 @@ public static partial class HandlersCollectionExtensions
"Ocelot", "BouncyCastle", "IdentityModel", "Telegrator"
];
+ ///
+ /// Collects all handlers from current app domain.
+ /// Scans for handlers exported by analyzer into class `Telegrator.Analyzers.AnalyzerExport` in each assembly and registers them to the collection.
+ ///
+ ///
+ ///
+ public static IHandlersCollection CollectHandlers(this IHandlersCollection handlers)
+ {
+ const string exportClassName = "Telegrator.Analyzers.AnalyzerExport";
+ AppDomain.CurrentDomain.GetAssemblies()
+ .Select(ass => ass.GetType(exportClassName))
+ .Squeeze()
+ .SelectMany(t => t.GetFields())
+ .Select(f => f.GetValue(null) as Type)
+ .Squeeze()
+ .ForEach(v => handlers.AddHandler(v));
+
+ return handlers;
+ }
+
///
/// Collects all public handlers from the current app domain.
/// Scans for types that implement handlers and adds them to the collection.
@@ -438,7 +458,7 @@ public static partial class HandlersCollectionExtensions
{
(collectingTarget ?? Assembly.GetCallingAssembly())
.GetExportedTypes()
- .Where(type => type.GetCustomAttribute() == null && type.IsHandlerRealization())
+ .Where(type => type.GetCustomAttribute() == null && type.IsHandlerImplementation())
.ForEach(type => handlers.AddHandler(type));
return handlers;
@@ -496,7 +516,7 @@ public static partial class HandlersCollectionExtensions
/// Thrown when the type is not a valid handler implementation.
public static IHandlersCollection AddHandler(this IHandlersCollection handlers, Type handlerType)
{
- if (!handlerType.IsHandlerRealization())
+ if (!handlerType.IsHandlerImplementation())
throw new Exception();
if (handlerType.IsCustomDescriptorsProvider())