99using Telegram . Bot . Types . Payments ;
1010using Telegram . Net . Attributes ;
1111using Telegram . Net . Interfaces ;
12+ using static System . Reflection . BindingFlags ;
13+
1214#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
1315
1416namespace Telegram . Net . Services ;
@@ -18,12 +20,12 @@ public class TelegramHostedService : IHostedService
1820 private IServiceCollection isc { get ; }
1921 internal TelegramBotClient Client { get ; set ; }
2022 private ITelegramBotConfig Config { get ; }
21- internal Dictionary < string , Func < ITelegramBotClient , Message , CancellationToken , Task > > CommandHandler { get ; } = new ( ) ;
22- internal List < Func < ITelegramBotClient , Message , CancellationToken , Task > > EditedMessageHandler { get ; } = new ( ) ;
23- internal Dictionary < string , Func < ITelegramBotClient , CallbackQuery , CancellationToken , Task > > CallbackQueryHandler { get ; } = new ( ) ;
24- internal Dictionary < string , Func < ITelegramBotClient , InlineQuery , CancellationToken , Task > > InlineHandler { get ; } = new ( ) ;
23+ internal Dictionary < string , Func < ITelegramBotClient , Message , CancellationToken , Task > > CommandHandler { get ; set ; } = new ( ) ;
24+ internal List < Func < ITelegramBotClient , Message , CancellationToken , Task > > EditedMessageHandler { get ; set ; } = new ( ) ;
25+ internal Dictionary < string , Func < ITelegramBotClient , CallbackQuery , CancellationToken , Task > > CallbackQueryHandler { get ; set ; } = new ( ) ;
26+ internal Dictionary < string , Func < ITelegramBotClient , InlineQuery , CancellationToken , Task > > InlineHandler { get ; set ; } = new ( ) ;
2527 internal Func < ITelegramBotClient , PreCheckoutQuery , CancellationToken , Task > ? PreCheckoutHandler { get ; set ; }
26- internal List < Func < ITelegramBotClient , Update , CancellationToken , Task > > DefaultUpdateHandler { get ; } = new ( ) ;
28+ internal List < Func < ITelegramBotClient , Update , CancellationToken , Task > > DefaultUpdateHandler { get ; set ; } = new ( ) ;
2729 internal static ILogger < TelegramHostedService > _logger ;
2830
2931 public TelegramHostedService ( ITelegramBotConfig config , IServiceCollection isc , ILogger < TelegramHostedService > logger )
@@ -73,116 +75,82 @@ internal static Func<ITelegramBotClient, T, CancellationToken, Task> CreateDeleg
7375 }
7476
7577 }
76-
78+
79+
80+
7781 internal async Task AddAttributes ( CancellationToken cancellationToken )
7882 {
7983 await Task . Run ( async ( ) =>
8084 {
8185 try
8286 {
83- var implementations = AppDomain . CurrentDomain . GetAssemblies ( )
84- . SelectMany ( a => a . GetTypes ( ) )
85- . Where ( t => typeof ( IUpdatePollingService ) . IsAssignableFrom ( t ) && ! t . IsInterface ) ;
86-
87- foreach ( var implementation in implementations )
87+ var attributeTypes = new HashSet < Type >
8888 {
89- isc . AddScoped ( implementation ) ;
90- }
91-
92- var methods = implementations
93- . SelectMany ( t => t . GetMethods (
94- BindingFlags . Instance |
95- BindingFlags . Public | BindingFlags . NonPublic |
96- BindingFlags . DeclaredOnly ) )
97- . Where ( m =>
98- m . GetCustomAttribute < CommandAttribute > ( ) != null ||
99- m . GetCustomAttribute < CallbackAttribute > ( ) != null ||
100- m . GetCustomAttribute < EditMessageAttribute > ( ) != null ||
101- m . GetCustomAttribute < InlineAttribute > ( ) != null ||
102- m . GetCustomAttribute < PreCheckoutAttribute > ( ) != null ||
103- m . GetCustomAttribute < UpdateAttribute > ( ) != null ) ;
104-
105- if ( methods . Count ( ) == 0 )
89+ typeof ( CommandAttribute ) ,
90+ typeof ( CallbackAttribute ) ,
91+ typeof ( EditMessageAttribute ) ,
92+ typeof ( InlineAttribute ) ,
93+ typeof ( PreCheckoutAttribute ) ,
94+ typeof ( UpdateAttribute )
95+ } ;
96+
97+ var methods = AppDomain . CurrentDomain . GetAssemblies ( )
98+ . SelectMany ( a => a . GetTypes ( ) )
99+ . Where ( t => typeof ( IUpdatePollingService ) . IsAssignableFrom ( t ) && ! t . IsInterface )
100+ . SelectMany ( t => t . GetMethods ( Instance |
101+ Public |
102+ NonPublic |
103+ DeclaredOnly ) )
104+ . Where ( m => m . GetCustomAttributes ( ) . Any ( a => attributeTypes . Contains ( a . GetType ( ) ) ) )
105+ . ToList ( ) ;
106+
107+ if ( methods . Count == 0 )
106108 {
107- _logger . LogWarning ( "Not founded methods with attributes. " ) ;
109+ _logger . LogWarning ( "No methods found with required attributes" ) ;
108110 }
109111
110- await Task . Delay ( TimeSpan . FromSeconds ( 1 ) , cancellationToken ) ;
112+ var isp = isc . BuildServiceProvider ( ) ;
111113 foreach ( var method in methods )
112114 {
113- var commandAttr = method . GetCustomAttribute < CommandAttribute > ( ) ;
114- if ( commandAttr != null )
115- {
116- if ( IsValidHandlerMethod ( method , typeof ( Message ) ) )
117- {
118- var handler = CreateDelegate < Message > ( method ) ;
119- if ( ! CommandHandler . TryAdd ( commandAttr . Command , handler ) )
120- throw new Exception ( $ "Failed to add in commandHandler: { commandAttr . Command } ") ;
121- }
122-
123- continue ;
124- }
125-
126- var callbackAttr = method . GetCustomAttribute < CallbackAttribute > ( ) ;
127- if ( callbackAttr != null )
128- {
129- if ( IsValidHandlerMethod ( method , typeof ( CallbackQuery ) ) )
130- {
131- var handler = CreateDelegate < CallbackQuery > ( method ) ;
132- if ( ! CallbackQueryHandler . TryAdd ( callbackAttr . QueryId , handler ) )
133- throw new Exception ( $ "Failed to add in callbacKQuery: { callbackAttr . QueryId } ") ; ;
134- }
135-
136- continue ;
137- }
138-
139- var editMessageAttr = method . GetCustomAttribute < EditMessageAttribute > ( ) ;
140- if ( editMessageAttr != null )
141- {
142- if ( IsValidHandlerMethod ( method , typeof ( Message ) ) )
143- {
144- var handler = CreateDelegate < Message > ( method ) ;
145- EditedMessageHandler . Add ( handler ) ;
146- }
147-
148- continue ;
149- }
150-
151- var inlineAttr = method . GetCustomAttribute < InlineAttribute > ( ) ;
152- if ( inlineAttr != null )
153- {
154- if ( IsValidHandlerMethod ( method , typeof ( InlineQuery ) ) )
155- {
156- var handler = CreateDelegate < InlineQuery > ( method ) ;
157- if ( ! InlineHandler . TryAdd ( inlineAttr . InlineId , handler ) )
158- throw new Exception ( $ "Failed to add in inlineHandler: { inlineAttr . InlineId } ") ; ;
159- }
160-
161- continue ;
162- }
163-
164- var preCheckoutAttr = method . GetCustomAttribute < PreCheckoutAttribute > ( ) ;
165- if ( preCheckoutAttr != null )
166- {
167- if ( IsValidHandlerMethod ( method , typeof ( PreCheckoutQuery ) ) )
168- {
169- var handler = CreateDelegate < PreCheckoutQuery > ( method ) ;
170- PreCheckoutHandler = handler ;
171- }
172-
173- continue ;
174- }
115+ var declaringType = method . DeclaringType ! ;
116+ var constructor = declaringType . GetConstructors ( ) [ 0 ] ;
117+ var parameters = constructor . GetParameters ( )
118+ . Select ( param => isp . GetRequiredService ( param . ParameterType ) )
119+ . ToArray ( ) ;
120+
121+ constructor . Invoke ( parameters ) ;
175122
176- var updateAttr = method . GetCustomAttribute < UpdateAttribute > ( ) ;
177- if ( updateAttr != null )
123+ switch ( method . GetCustomAttributes ( ) . First ( t => attributeTypes . Contains ( t . GetType ( ) ) ) )
178124 {
179- if ( IsValidHandlerMethod ( method , typeof ( Update ) ) )
180- {
181- var handler = CreateDelegate < Update > ( method ) ;
182- DefaultUpdateHandler . Add ( handler ) ;
183- }
184-
185- continue ;
125+ case CommandAttribute command when IsValidHandlerMethod ( method , typeof ( Message ) ) :
126+ var commandHandler = CreateDelegate < Message > ( method ) ;
127+ if ( ! CommandHandler . TryAdd ( command . Command , commandHandler ) )
128+ throw new Exception ( $ "Failed to add command: { command . Command } ") ;
129+ break ;
130+
131+ case CallbackAttribute callback when IsValidHandlerMethod ( method , typeof ( CallbackQuery ) ) :
132+ var callbackHandler = CreateDelegate < CallbackQuery > ( method ) ;
133+ if ( ! CallbackQueryHandler . TryAdd ( callback . QueryId , callbackHandler ) )
134+ throw new Exception ( $ "Failed to add callback: { callback . QueryId } ") ;
135+ break ;
136+
137+ case EditMessageAttribute _ when IsValidHandlerMethod ( method , typeof ( Message ) ) :
138+ EditedMessageHandler . Add ( CreateDelegate < Message > ( method ) ) ;
139+ break ;
140+
141+ case InlineAttribute inline when IsValidHandlerMethod ( method , typeof ( InlineQuery ) ) :
142+ var inlineHandler = CreateDelegate < InlineQuery > ( method ) ;
143+ if ( ! InlineHandler . TryAdd ( inline . InlineId , inlineHandler ) )
144+ throw new Exception ( $ "Failed to add inline: { inline . InlineId } ") ;
145+ break ;
146+
147+ case PreCheckoutAttribute _ when IsValidHandlerMethod ( method , typeof ( PreCheckoutQuery ) ) :
148+ PreCheckoutHandler = CreateDelegate < PreCheckoutQuery > ( method ) ;
149+ break ;
150+
151+ case UpdateAttribute _ when IsValidHandlerMethod ( method , typeof ( Update ) ) :
152+ DefaultUpdateHandler . Add ( CreateDelegate < Update > ( method ) ) ;
153+ break ;
186154 }
187155 }
188156 }
0 commit comments