Generated registration¶
В TeleFlow есть два поддерживаемых пути регистрации handlers для нового кода:
- generated assembly registration;
- explicit direct registration.
Deprecated reflection assembly API остаётся только как временный migration path до 1.0.
Рекомендуемый default для application code - generated assembly registration.
Зачем нужен generated registration¶
Assembly scanning удобен, но runtime reflection как скрытый default усложняет startup reasoning. TeleFlow сохраняет удобство, но переносит metadata creation в build time.
Практический эффект:
- missing metadata ловится на startup;
- generated metadata можно проверять analyzers;
- reflection не является silent fallback для assembly registration.
Настройка¶
Project file:
<PackageReference Include="IWF.TeleFlow.Framework.LongPolling" Version="..." />
<PackageReference Include="IWF.TeleFlow.Generators" Version="..." PrivateAssets="all" />
Startup:
builder.Services.AddTelegramBot(options => options.Token = token);
builder.Services.AddTelegramHandlersFromAssembly(typeof(Program).Assembly);
builder.Services.AddLongPolling();
Handler:
public sealed class StartHandler
{
[Command("start")]
public Task Handle(MessageContext ctx, CancellationToken ct)
{
return ctx.Message.AnswerAsync("Ready.", ct);
}
}
Семантика ошибок¶
AddTelegramHandlersFromAssembly(...) ожидает generated Telegram handler metadata в target assembly.
Если metadata не найдена, он бросает exception. Он не сканирует assembly через reflection молча.
Это важно для production code. Missing generator package - configuration mistake, а не причина менять runtime behavior.
Контракт регистрации¶
TeleFlow намеренно разделяет assembly registration и explicit type registration.
AddTelegramHandlersFromAssembly(assembly) означает:
- зарегистрировать generated metadata для этого assembly;
- требовать
IWF.TeleFlow.Generators; - упасть, если generated metadata отсутствует;
- никогда не сканировать assembly как fallback.
AddTelegramHandler<THandler>() означает:
- зарегистрировать ровно указанный handler type;
- построить metadata для этого type на startup;
- не сканировать containing assembly;
- не требовать generator.
AddTelegramModule<TModule>() означает:
- зарегистрировать ровно указанный module type;
- требовать
[TelegramModule]на module type; - использовать generated metadata для этого module, если она доступна;
- иначе построить metadata для этого module type на startup;
- не сканировать containing assembly.
Direct path сделан явным специально. Он удобен для tests, маленьких examples и manually composed modules. Для больших приложений это не recommended default, потому что каждый handler нужно перечислять руками.
Прямая регистрация¶
Direct registration не требует generator:
builder.Services.AddTelegramHandler<StartHandler>();
builder.Services.AddTelegramModule<AdminHandlers>();
Используй её для:
- маленьких examples;
- tests;
- manually composed modules;
- случаев, когда handler list должен быть очевиден на registration site.
Deprecated reflection registration¶
Reflection assembly registration объявлен deprecated и будет удалён до 1.0:
Не используй его в новых проектах. Для обычных приложений используй generated assembly registration, а для ручного контроля - direct registration с явным списком handlers/modules.
Что генерируется¶
Generated metadata описывает:
- handler type and method;
- route kind;
- route attributes;
- built-in filter metadata;
- state and scene metadata;
- callback payload metadata и generated compact callback data codecs;
- error handlers;
- auto-answer callback metadata;
- generated invokers.
Обычно generated types напрямую не вызываются.
Generated callback data codecs¶
[CallbackData] payloads достаточно статичны, чтобы сгенерировать прямой pack/unpack code.
Когда generator установлен, TeleFlow эмитит assembly-level callback data codec registrar
вместе с handler metadata. Runtime один раз находит registrar для payload assembly и
кэширует generated delegates.
Generated codec используется в:
InlineKeyboardBuilder.Build(), когда он пакует typed callback buttons;- default
ICallbackDataSerializer; - typed
[Callback<TPayload>]route matching.
Wire format не меняется: prefix:field1:field2. Уже существующая compact callback
data остаётся совместимой. Generated path убирает повторную field reflection из
обычной обработки callback; explicit direct registration и deprecated reflection
registration всё ещё могут использовать runtime metadata fallback.
Analyzer feedback¶
IWF.TeleFlow.Generators также содержит analyzer checks для invalid handler shapes, route usage, callback payloads, scene state definitions и error handler signatures.
Держи analyzer warnings видимыми в CI. Это часть framework contract.
Текущие diagnostic ids:
| Id | Что означает |
|---|---|
TLF001 |
Несколько route attributes на одном handler method. |
TLF002 |
Неподдерживаемый handler return type. |
TLF003 |
Invalid или missing context parameter. |
TLF004 |
Больше одного CancellationToken. |
TLF005 |
Invalid command name. |
TLF006 |
Text filter используется на callback handler. |
TLF007 |
Duplicate command handler. |
TLF008 |
Invalid handler type. |
TLF009 |
Invalid handler method. |
TLF010 |
Invalid callback data payload. |
TLF011 |
Duplicate callback data prefix. |
TLF012 |
Invalid state group. |
TLF013 |
Invalid typed state reference. |
TLF014 |
Invalid typed callback handler. |
TLF015 |
Invalid Telegram module. |
TLF016 |
Invalid route template. |
TLF017 |
Invalid route regex. |
TLF018 |
Invalid route value binding. |
TLF019 |
Invalid filter usage. |
TLF020 |
Handler method унаследован с другого type. |
TLF021 |
Invalid command prefix. |
TLF022 |
Invalid scene. |
TLF023 |
Invalid scene step. |
TLF024 |
Invalid auto-answer callback usage. |
TLF025 |
Invalid class-based handler. |
TLF026 |
Invalid error handler. |
Рекомендуемая policy¶
Для production apps:
- используй generated assembly registration by default;
- держи
IWF.TeleFlow.Generatorsprivate черезPrivateAssets="all"; - используй direct registration в tests, где это улучшает clarity;
- используй reflection assembly registration только как deprecated migration path во время миграции.