|
9 | 9 | using Telegram.Bot.Types.Payments; |
10 | 10 | using Telegram.Net.Attributes; |
11 | 11 | using Telegram.Net.Interfaces; |
| 12 | +using static System.Reflection.BindingFlags; |
| 13 | + |
12 | 14 | #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously |
13 | 15 |
|
14 | 16 | namespace Telegram.Net.Services; |
@@ -73,116 +75,85 @@ internal static Func<ITelegramBotClient, T, CancellationToken, Task> CreateDeleg |
73 | 75 | } |
74 | 76 |
|
75 | 77 | } |
76 | | - |
| 78 | + |
| 79 | + |
| 80 | + |
77 | 81 | internal async Task AddAttributes(CancellationToken cancellationToken) |
78 | 82 | { |
79 | 83 | await Task.Run(async () => |
80 | 84 | { |
81 | 85 | try |
82 | 86 | { |
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> |
88 | 88 | { |
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) |
106 | 108 | { |
107 | | - _logger.LogWarning("Not founded methods with attributes."); |
| 109 | + _logger.LogWarning("No methods found with required attributes"); |
108 | 110 | } |
109 | 111 |
|
110 | | - await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); |
| 112 | + var isp = isc.BuildServiceProvider(); |
111 | 113 | foreach (var method in methods) |
112 | 114 | { |
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 | | - } |
| 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); |
163 | 122 |
|
164 | | - var preCheckoutAttr = method.GetCustomAttribute<PreCheckoutAttribute>(); |
165 | | - if (preCheckoutAttr != null) |
| 123 | + void AddHandler<T>(Dictionary<string, Func<ITelegramBotClient, T, CancellationToken, Task>> dictionary, string key) where T : class |
166 | 124 | { |
167 | | - if (IsValidHandlerMethod(method, typeof(PreCheckoutQuery))) |
168 | | - { |
169 | | - var handler = CreateDelegate<PreCheckoutQuery>(method); |
170 | | - PreCheckoutHandler = handler; |
171 | | - } |
172 | | - |
173 | | - continue; |
| 125 | + if (!IsValidHandlerMethod(method, typeof(T))) return; |
| 126 | + |
| 127 | + var handler = CreateDelegate<T>(method); |
| 128 | + if (!dictionary.TryAdd(key, handler)) |
| 129 | + throw new Exception($"Failed to add {key} to {dictionary.GetType().Name}"); |
174 | 130 | } |
175 | 131 |
|
176 | | - var updateAttr = method.GetCustomAttribute<UpdateAttribute>(); |
177 | | - if (updateAttr != null) |
| 132 | + switch (method.GetCustomAttributes().FirstOrDefault()) |
178 | 133 | { |
179 | | - if (IsValidHandlerMethod(method, typeof(Update))) |
180 | | - { |
181 | | - var handler = CreateDelegate<Update>(method); |
182 | | - DefaultUpdateHandler.Add(handler); |
183 | | - } |
184 | | - |
185 | | - continue; |
| 134 | + case CommandAttribute command: |
| 135 | + AddHandler(CommandHandler, command.Command); |
| 136 | + break; |
| 137 | + |
| 138 | + case CallbackAttribute callback: |
| 139 | + AddHandler(CallbackQueryHandler, callback.QueryId); |
| 140 | + break; |
| 141 | + |
| 142 | + case EditMessageAttribute _ when IsValidHandlerMethod(method, typeof(Message)): |
| 143 | + EditedMessageHandler.Add(CreateDelegate<Message>(method)); |
| 144 | + break; |
| 145 | + |
| 146 | + case InlineAttribute inline: |
| 147 | + AddHandler(InlineHandler, inline.InlineId); |
| 148 | + break; |
| 149 | + |
| 150 | + case PreCheckoutAttribute _ when IsValidHandlerMethod(method, typeof(PreCheckoutQuery)): |
| 151 | + PreCheckoutHandler = CreateDelegate<PreCheckoutQuery>(method); |
| 152 | + break; |
| 153 | + |
| 154 | + case UpdateAttribute _ when IsValidHandlerMethod(method, typeof(Update)): |
| 155 | + DefaultUpdateHandler.Add(CreateDelegate<Update>(method)); |
| 156 | + break; |
186 | 157 | } |
187 | 158 | } |
188 | 159 | } |
|
0 commit comments