From 1fbee046fdc4a96fd0da0cfa7078ac1f1039796c Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 00:15:26 +0300 Subject: [PATCH 1/9] Add fallbackForm parameter to session serializer methods Extended ISessionSerializationStage interface methods to accept an optional fallbackForm parameter for UseJSON, UseSimpleJSON, and UseXML overloads. This allows specifying a fallback form type for session serialization. --- .../Interfaces/ISessionSerializationStage.cs | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/TelegramBotBase/Builder/Interfaces/ISessionSerializationStage.cs b/TelegramBotBase/Builder/Interfaces/ISessionSerializationStage.cs index e4991c2..b871992 100644 --- a/TelegramBotBase/Builder/Interfaces/ISessionSerializationStage.cs +++ b/TelegramBotBase/Builder/Interfaces/ISessionSerializationStage.cs @@ -30,10 +30,10 @@ public interface ISessionSerializationStage /// /// For the legacy version use the UseNewtonsoftJson method of TelegramBotBase.Extensions.Serializer.Legacy.NewtonsoftJson /// - /// + /// /// /// - ILanguageSelectionStage UseJSON(); + ILanguageSelectionStage UseJSON(Type fallbackForm = null); /// /// Using the complex version of .Net JSON, which can serialize all objects. @@ -47,39 +47,42 @@ public interface ISessionSerializationStage /// For the legacy version use the UseNewtonsoftJson method of TelegramBotBase.Extensions.Serializer.Legacy.NewtonsoftJson /// /// + /// /// /// - ILanguageSelectionStage UseJSON(string path); + ILanguageSelectionStage UseJSON(string path, Type fallbackForm = null); /// /// Use the easy version of .Net JSON, which can serialize basic types, but not generics and others. /// Saves in application directory. /// - /// + /// /// [Obsolete("Use UseJSON instead.")] - ILanguageSelectionStage UseSimpleJSON(); + ILanguageSelectionStage UseSimpleJSON(Type fallbackForm = null); /// /// Use the easy version of .Net JSON, which can serialize basic types, but not generics and others. /// /// + /// /// [Obsolete("Use UseJSON instead.")] - ILanguageSelectionStage UseSimpleJSON(string path); + ILanguageSelectionStage UseSimpleJSON(string path, Type fallbackForm = null); /// /// Uses the XML serializer for session serialization. /// Saves in application directory. /// - /// + /// /// - ILanguageSelectionStage UseXML(); + ILanguageSelectionStage UseXML(Type fallbackForm = null); /// /// Uses the XML serializer for session serialization. /// /// + /// /// - ILanguageSelectionStage UseXML(string path); + ILanguageSelectionStage UseXML(string path, Type fallbackForm = null); } \ No newline at end of file From b889d9f00da8bc74efa3ca89e600e7aff6066fd9 Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 00:15:50 +0300 Subject: [PATCH 2/9] Add fallbackForm parameter to state machine methods Extended UseJSON, UseSimpleJSON, and UseXML methods to accept an optional fallbackForm Type parameter, allowing specification of a fallback form for state machine initialization. This enhances flexibility in state management by enabling a default form to be set when loading or writing state files. --- TelegramBotBase/Builder/BotBaseBuilder.cs | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/TelegramBotBase/Builder/BotBaseBuilder.cs b/TelegramBotBase/Builder/BotBaseBuilder.cs index 44690d6..803d71f 100644 --- a/TelegramBotBase/Builder/BotBaseBuilder.cs +++ b/TelegramBotBase/Builder/BotBaseBuilder.cs @@ -356,10 +356,10 @@ public ILanguageSelectionStage UseSerialization(IStateMachine machine) /// /// For the legacy version use the UseNewtonsoftJson method of TelegramBotBase.Extensions.Serializer.Legacy.NewtonsoftJson /// - public ILanguageSelectionStage UseJSON() + public ILanguageSelectionStage UseJSON(Type fallbackForm = null) { var path = Path.Combine(Directory.GetCurrentDirectory(), "states.json"); - _stateMachine = new JsonStateMachine(path); + _stateMachine = new JsonStateMachine(path, fallbackForm); return this; } @@ -368,9 +368,9 @@ public ILanguageSelectionStage UseJSON() /// /// For the legacy version use the UseNewtonsoftJson method of TelegramBotBase.Extensions.Serializer.Legacy.NewtonsoftJson /// - public ILanguageSelectionStage UseJSON(string path) + public ILanguageSelectionStage UseJSON(string path, Type fallbackForm = null) { - _stateMachine = new JsonStateMachine(path); + _stateMachine = new JsonStateMachine(path, fallbackForm); return this; } @@ -378,10 +378,10 @@ public ILanguageSelectionStage UseJSON(string path) /// Uses the application runtime path to load and write a states.json file. /// /// - public ILanguageSelectionStage UseSimpleJSON() + public ILanguageSelectionStage UseSimpleJSON(Type fallbackForm = null) { var path = Path.Combine(Directory.GetCurrentDirectory(), "states.json"); - _stateMachine = new SimpleJsonStateMachine(path); + _stateMachine = new SimpleJsonStateMachine(path, fallbackForm); return this; } @@ -389,9 +389,9 @@ public ILanguageSelectionStage UseSimpleJSON() /// Uses the given path to load and write a states.json file. /// /// - public ILanguageSelectionStage UseSimpleJSON(string path) + public ILanguageSelectionStage UseSimpleJSON(string path, Type fallbackForm = null) { - _stateMachine = new SimpleJsonStateMachine(path); + _stateMachine = new SimpleJsonStateMachine(path, fallbackForm); return this; } @@ -399,10 +399,10 @@ public ILanguageSelectionStage UseSimpleJSON(string path) /// Uses the application runtime path to load and write a states.xml file. /// /// - public ILanguageSelectionStage UseXML() + public ILanguageSelectionStage UseXML(Type fallbackForm = null) { var path = Path.Combine(Directory.GetCurrentDirectory(), "states.xml"); - _stateMachine = new XmlStateMachine(path); + _stateMachine = new XmlStateMachine(path, fallbackForm); return this; } @@ -410,9 +410,9 @@ public ILanguageSelectionStage UseXML() /// Uses the given path to load and write a states.xml file. /// /// - public ILanguageSelectionStage UseXML(string path) + public ILanguageSelectionStage UseXML(string path, Type fallbackForm = null) { - _stateMachine = new XmlStateMachine(path); + _stateMachine = new XmlStateMachine(path, fallbackForm); return this; } From 0dfa33455fbdbd6433e39652d2405575a7d7790f Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 00:39:44 +0300 Subject: [PATCH 3/9] Refactor StartFormFactory to FormFactory Renamed IStartFormFactory and related classes to IFormFactory for broader applicability beyond just start forms. Updated all references, method signatures, and class names to reflect this change, improving clarity and consistency in the codebase. --- TelegramBotBase/BotBase.cs | 2 +- TelegramBotBase/Builder/BotBaseBuilder.cs | 22 +++++++++---------- .../Interfaces/IAPIKeySelectionStage.cs | 4 ++-- .../Interfaces/IStartFormSelectionStage.cs | 8 +++---- ...rtFormFactory.cs => DefaultFormFactory.cs} | 4 ++-- ...artFormFactory.cs => LambdaFormFactory.cs} | 4 ++-- ...ctory.cs => ServiceProviderFormFactory.cs} | 8 +++---- .../{IStartFormFactory.cs => IFormFactory.cs} | 2 +- TelegramBotBase/SessionManager.cs | 2 +- 9 files changed, 28 insertions(+), 28 deletions(-) rename TelegramBotBase/Factories/{DefaultStartFormFactory.cs => DefaultFormFactory.cs} (83%) rename TelegramBotBase/Factories/{LambdaStartFormFactory.cs => LambdaFormFactory.cs} (73%) rename TelegramBotBase/Factories/{ServiceProviderStartFormFactory.cs => ServiceProviderFormFactory.cs} (76%) rename TelegramBotBase/Interfaces/{IStartFormFactory.cs => IFormFactory.cs} (74%) diff --git a/TelegramBotBase/BotBase.cs b/TelegramBotBase/BotBase.cs index 6994fab..1d60dca 100644 --- a/TelegramBotBase/BotBase.cs +++ b/TelegramBotBase/BotBase.cs @@ -68,7 +68,7 @@ internal BotBase(string apiKey, MessageClient client) /// /// Offers functionality to manage the creation process of the start form. /// - public IStartFormFactory StartFormFactory { get; internal set; } + public IFormFactory FormFactory { get; internal set; } /// /// Contains the message loop factory, which cares about "message-management." diff --git a/TelegramBotBase/Builder/BotBaseBuilder.cs b/TelegramBotBase/Builder/BotBaseBuilder.cs index 803d71f..6159a6c 100644 --- a/TelegramBotBase/Builder/BotBaseBuilder.cs +++ b/TelegramBotBase/Builder/BotBaseBuilder.cs @@ -25,7 +25,7 @@ public class BotBaseBuilder : IAPIKeySelectionStage, IMessageLoopSelectionStage, private MessageClient _client; - private IStartFormFactory _factory; + private IFormFactory _factory; private IMessageLoopFactory _messageLoopFactory; @@ -49,7 +49,7 @@ public BotBase Build() { var bot = new BotBase(_apiKey, _client) { - StartFormFactory = _factory, + FormFactory = _factory, BotCommandScopes = BotCommandScopes, StateMachine = _stateMachine, MessageLoopFactory = _messageLoopFactory @@ -75,7 +75,7 @@ public IMessageLoopSelectionStage WithAPIKey(string apiKey) public IBuildingStage QuickStart(string apiKey, Type startForm, bool throwPendingUpdates = false) { _apiKey = apiKey; - _factory = new DefaultStartFormFactory(startForm); + _factory = new DefaultFormFactory(startForm); DefaultMessageLoop(); @@ -97,7 +97,7 @@ public IBuildingStage QuickStart(string apiKey, bool throwPendingUpdates = fa where T : FormBase { _apiKey = apiKey; - _factory = new DefaultStartFormFactory(typeof(T)); + _factory = new DefaultFormFactory(typeof(T)); DefaultMessageLoop(); @@ -114,10 +114,10 @@ public IBuildingStage QuickStart(string apiKey, bool throwPendingUpdates = fa return this; } - public IBuildingStage QuickStart(string apiKey, IStartFormFactory startFormFactory, bool throwPendingUpdates = false) + public IBuildingStage QuickStart(string apiKey, IFormFactory formFactory, bool throwPendingUpdates = false) { _apiKey = apiKey; - _factory = startFormFactory; + _factory = formFactory; DefaultMessageLoop(); @@ -200,31 +200,31 @@ public IStartFormSelectionStage CustomMessageLoop() public INetworkingSelectionStage WithStartForm(Type startFormClass) { - _factory = new DefaultStartFormFactory(startFormClass); + _factory = new DefaultFormFactory(startFormClass); return this; } public INetworkingSelectionStage WithStartForm() where T : FormBase, new() { - _factory = new DefaultStartFormFactory(typeof(T)); + _factory = new DefaultFormFactory(typeof(T)); return this; } public INetworkingSelectionStage WithServiceProvider(Type startFormClass, IServiceProvider serviceProvider) { - _factory = new ServiceProviderStartFormFactory(startFormClass, serviceProvider); + _factory = new ServiceProviderFormFactory(startFormClass, serviceProvider); return this; } public INetworkingSelectionStage WithServiceProvider(IServiceProvider serviceProvider) where T : FormBase { - _factory = new ServiceProviderStartFormFactory(serviceProvider); + _factory = new ServiceProviderFormFactory(serviceProvider); return this; } - public INetworkingSelectionStage WithStartFormFactory(IStartFormFactory factory) + public INetworkingSelectionStage WithFormFactory(IFormFactory factory) { _factory = factory; return this; diff --git a/TelegramBotBase/Builder/Interfaces/IAPIKeySelectionStage.cs b/TelegramBotBase/Builder/Interfaces/IAPIKeySelectionStage.cs index 45d439f..fbcea89 100644 --- a/TelegramBotBase/Builder/Interfaces/IAPIKeySelectionStage.cs +++ b/TelegramBotBase/Builder/Interfaces/IAPIKeySelectionStage.cs @@ -38,8 +38,8 @@ public interface IAPIKeySelectionStage /// Uses: DefaultMessageLoop, NoProxy, OnlyStart, NoSerialization, DefaultLanguage /// /// - /// + /// /// Indicates if all pending Telegram.Bot.Types.Updates should be thrown out before start polling. /// - IBuildingStage QuickStart(string apiKey, IStartFormFactory StartFormFactory, bool throwPendingUpdates = false); + IBuildingStage QuickStart(string apiKey, IFormFactory formFactory, bool throwPendingUpdates = false); } \ No newline at end of file diff --git a/TelegramBotBase/Builder/Interfaces/IStartFormSelectionStage.cs b/TelegramBotBase/Builder/Interfaces/IStartFormSelectionStage.cs index 1254693..0d26b01 100644 --- a/TelegramBotBase/Builder/Interfaces/IStartFormSelectionStage.cs +++ b/TelegramBotBase/Builder/Interfaces/IStartFormSelectionStage.cs @@ -21,7 +21,7 @@ public interface IStartFormSelectionStage INetworkingSelectionStage WithStartForm() where T : FormBase, new(); /// - /// Chooses a StartFormFactory which will be use for new sessions. + /// Chooses a FormFactory which will be use for new sessions. /// /// /// @@ -29,7 +29,7 @@ public interface IStartFormSelectionStage INetworkingSelectionStage WithServiceProvider(Type startFormClass, IServiceProvider serviceProvider); /// - /// Chooses a StartFormFactory which will be use for new sessions. + /// Chooses a FormFactory which will be use for new sessions. /// /// /// @@ -37,9 +37,9 @@ public interface IStartFormSelectionStage INetworkingSelectionStage WithServiceProvider(IServiceProvider serviceProvider) where T : FormBase; /// - /// Chooses a StartFormFactory which will be use for new sessions. + /// Chooses a FormFactory which will be use for new sessions. /// /// /// - INetworkingSelectionStage WithStartFormFactory(IStartFormFactory factory); + INetworkingSelectionStage WithFormFactory(IFormFactory factory); } \ No newline at end of file diff --git a/TelegramBotBase/Factories/DefaultStartFormFactory.cs b/TelegramBotBase/Factories/DefaultFormFactory.cs similarity index 83% rename from TelegramBotBase/Factories/DefaultStartFormFactory.cs rename to TelegramBotBase/Factories/DefaultFormFactory.cs index a908c85..0110734 100644 --- a/TelegramBotBase/Factories/DefaultStartFormFactory.cs +++ b/TelegramBotBase/Factories/DefaultFormFactory.cs @@ -4,11 +4,11 @@ namespace TelegramBotBase.Factories; -public class DefaultStartFormFactory : IStartFormFactory +public class DefaultFormFactory : IFormFactory { private readonly Type _startFormClass; - public DefaultStartFormFactory(Type startFormClass) + public DefaultFormFactory(Type startFormClass) { if (!typeof(FormBase).IsAssignableFrom(startFormClass)) { diff --git a/TelegramBotBase/Factories/LambdaStartFormFactory.cs b/TelegramBotBase/Factories/LambdaFormFactory.cs similarity index 73% rename from TelegramBotBase/Factories/LambdaStartFormFactory.cs rename to TelegramBotBase/Factories/LambdaFormFactory.cs index 2ca4c5c..a370929 100644 --- a/TelegramBotBase/Factories/LambdaStartFormFactory.cs +++ b/TelegramBotBase/Factories/LambdaFormFactory.cs @@ -3,13 +3,13 @@ namespace TelegramBotBase.Factories; -public class LambdaStartFormFactory : IStartFormFactory +public class LambdaFormFactory : IFormFactory { public delegate FormBase CreateFormDelegate(); private readonly CreateFormDelegate _lambda; - public LambdaStartFormFactory(CreateFormDelegate lambda) + public LambdaFormFactory(CreateFormDelegate lambda) { _lambda = lambda; } diff --git a/TelegramBotBase/Factories/ServiceProviderStartFormFactory.cs b/TelegramBotBase/Factories/ServiceProviderFormFactory.cs similarity index 76% rename from TelegramBotBase/Factories/ServiceProviderStartFormFactory.cs rename to TelegramBotBase/Factories/ServiceProviderFormFactory.cs index f143604..acf7b96 100644 --- a/TelegramBotBase/Factories/ServiceProviderStartFormFactory.cs +++ b/TelegramBotBase/Factories/ServiceProviderFormFactory.cs @@ -7,12 +7,12 @@ namespace TelegramBotBase.Factories; -public class ServiceProviderStartFormFactory : IStartFormFactory +public class ServiceProviderFormFactory : IFormFactory { private readonly IServiceProvider _serviceProvider; private readonly Type _startFormClass; - public ServiceProviderStartFormFactory(Type startFormClass, IServiceProvider serviceProvider) + public ServiceProviderFormFactory(Type startFormClass, IServiceProvider serviceProvider) { if (!typeof(FormBase).IsAssignableFrom(startFormClass)) { @@ -43,10 +43,10 @@ public FormBase CreateForm() } } -public class ServiceProviderStartFormFactory : ServiceProviderStartFormFactory +public class ServiceProviderFormFactory : ServiceProviderFormFactory where T : FormBase { - public ServiceProviderStartFormFactory(IServiceProvider serviceProvider) : base(typeof(T), serviceProvider) + public ServiceProviderFormFactory(IServiceProvider serviceProvider) : base(typeof(T), serviceProvider) { } } \ No newline at end of file diff --git a/TelegramBotBase/Interfaces/IStartFormFactory.cs b/TelegramBotBase/Interfaces/IFormFactory.cs similarity index 74% rename from TelegramBotBase/Interfaces/IStartFormFactory.cs rename to TelegramBotBase/Interfaces/IFormFactory.cs index 28a2df2..aa86cc7 100644 --- a/TelegramBotBase/Interfaces/IStartFormFactory.cs +++ b/TelegramBotBase/Interfaces/IFormFactory.cs @@ -2,7 +2,7 @@ namespace TelegramBotBase.Interfaces; -public interface IStartFormFactory +public interface IFormFactory { FormBase CreateForm(); } \ No newline at end of file diff --git a/TelegramBotBase/SessionManager.cs b/TelegramBotBase/SessionManager.cs index 5e6975e..672ffdb 100644 --- a/TelegramBotBase/SessionManager.cs +++ b/TelegramBotBase/SessionManager.cs @@ -59,7 +59,7 @@ public IDeviceSession GetSession(long deviceId) /// public async Task StartSession(long deviceId) { - var start = BotBase.StartFormFactory.CreateForm(); + var start = BotBase.FormFactory.CreateForm(); start.Client = Client; From fb5d58e96217197ec0993c59b149d0bc20688786 Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 00:55:16 +0300 Subject: [PATCH 4/9] Rename CreateForm to CreateStartForm in form factories Refactored IFormFactory and its implementations to rename the CreateForm method to CreateStartForm for improved clarity. Updated SessionManager to use the new method name. --- TelegramBotBase/Factories/DefaultFormFactory.cs | 2 +- TelegramBotBase/Factories/LambdaFormFactory.cs | 2 +- TelegramBotBase/Factories/ServiceProviderFormFactory.cs | 2 +- TelegramBotBase/Interfaces/IFormFactory.cs | 2 +- TelegramBotBase/SessionManager.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/TelegramBotBase/Factories/DefaultFormFactory.cs b/TelegramBotBase/Factories/DefaultFormFactory.cs index 0110734..09240b5 100644 --- a/TelegramBotBase/Factories/DefaultFormFactory.cs +++ b/TelegramBotBase/Factories/DefaultFormFactory.cs @@ -19,7 +19,7 @@ public DefaultFormFactory(Type startFormClass) } - public FormBase CreateForm() + public FormBase CreateStartForm() { return _startFormClass.GetConstructor(new Type[] { })?.Invoke(new object[] { }) as FormBase; } diff --git a/TelegramBotBase/Factories/LambdaFormFactory.cs b/TelegramBotBase/Factories/LambdaFormFactory.cs index a370929..6edb9ad 100644 --- a/TelegramBotBase/Factories/LambdaFormFactory.cs +++ b/TelegramBotBase/Factories/LambdaFormFactory.cs @@ -14,7 +14,7 @@ public LambdaFormFactory(CreateFormDelegate lambda) _lambda = lambda; } - public FormBase CreateForm() + public FormBase CreateStartForm() { return _lambda(); } diff --git a/TelegramBotBase/Factories/ServiceProviderFormFactory.cs b/TelegramBotBase/Factories/ServiceProviderFormFactory.cs index acf7b96..26c57ee 100644 --- a/TelegramBotBase/Factories/ServiceProviderFormFactory.cs +++ b/TelegramBotBase/Factories/ServiceProviderFormFactory.cs @@ -23,7 +23,7 @@ public ServiceProviderFormFactory(Type startFormClass, IServiceProvider serviceP _serviceProvider = serviceProvider; } - public FormBase CreateForm() + public FormBase CreateStartForm() { FormBase fb = null; diff --git a/TelegramBotBase/Interfaces/IFormFactory.cs b/TelegramBotBase/Interfaces/IFormFactory.cs index aa86cc7..8019b38 100644 --- a/TelegramBotBase/Interfaces/IFormFactory.cs +++ b/TelegramBotBase/Interfaces/IFormFactory.cs @@ -4,5 +4,5 @@ namespace TelegramBotBase.Interfaces; public interface IFormFactory { - FormBase CreateForm(); + FormBase CreateStartForm(); } \ No newline at end of file diff --git a/TelegramBotBase/SessionManager.cs b/TelegramBotBase/SessionManager.cs index 672ffdb..e652074 100644 --- a/TelegramBotBase/SessionManager.cs +++ b/TelegramBotBase/SessionManager.cs @@ -59,7 +59,7 @@ public IDeviceSession GetSession(long deviceId) /// public async Task StartSession(long deviceId) { - var start = BotBase.FormFactory.CreateForm(); + var start = BotBase.FormFactory.CreateStartForm(); start.Client = Client; From ba60fe7c91310bf71d4733be3f6cb8621b409356 Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 00:55:31 +0300 Subject: [PATCH 5/9] Extend IFormFactory with generic and type-based creation Added CreateForm(Type formType) and CreateForm() methods to the IFormFactory interface to support more flexible form instantiation. --- TelegramBotBase/Interfaces/IFormFactory.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TelegramBotBase/Interfaces/IFormFactory.cs b/TelegramBotBase/Interfaces/IFormFactory.cs index 8019b38..48bf530 100644 --- a/TelegramBotBase/Interfaces/IFormFactory.cs +++ b/TelegramBotBase/Interfaces/IFormFactory.cs @@ -1,8 +1,11 @@ -using TelegramBotBase.Form; +using System; +using TelegramBotBase.Form; namespace TelegramBotBase.Interfaces; public interface IFormFactory { FormBase CreateStartForm(); + FormBase CreateForm(Type formType); + FormBase CreateForm() where T : FormBase, new(); } \ No newline at end of file From a2d4bdb197a0a22a1ff8ec1b8050ce38e78d93fa Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 00:55:55 +0300 Subject: [PATCH 6/9] Add generic CreateForm methods to form factories Introduced CreateForm(Type) and CreateForm() methods to DefaultFormFactory, LambdaFormFactory, and ServiceProviderFormFactory. This enhances flexibility by allowing creation of forms by type or generic parameter, and unifies the form creation interface across different factory implementations. --- TelegramBotBase/Factories/DefaultFormFactory.cs | 17 ++++++++++++++++- TelegramBotBase/Factories/LambdaFormFactory.cs | 16 +++++++++++++++- .../Factories/ServiceProviderFormFactory.cs | 17 ++++++++++++++++- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/TelegramBotBase/Factories/DefaultFormFactory.cs b/TelegramBotBase/Factories/DefaultFormFactory.cs index 09240b5..560d41c 100644 --- a/TelegramBotBase/Factories/DefaultFormFactory.cs +++ b/TelegramBotBase/Factories/DefaultFormFactory.cs @@ -21,6 +21,21 @@ public DefaultFormFactory(Type startFormClass) public FormBase CreateStartForm() { - return _startFormClass.GetConstructor(new Type[] { })?.Invoke(new object[] { }) as FormBase; + return CreateForm(_startFormClass); + } + + public FormBase CreateForm(Type formType) + { + if (!typeof(FormBase).IsAssignableFrom(formType)) + { + throw new ArgumentException($"{nameof(formType)} argument must be a {nameof(FormBase)} type"); + } + + return formType.GetConstructor(new Type[] { })?.Invoke(new object[] { }) as FormBase; + } + + public FormBase CreateForm() where T : FormBase, new() + { + return CreateForm(typeof(T)); } } \ No newline at end of file diff --git a/TelegramBotBase/Factories/LambdaFormFactory.cs b/TelegramBotBase/Factories/LambdaFormFactory.cs index 6edb9ad..5992ed4 100644 --- a/TelegramBotBase/Factories/LambdaFormFactory.cs +++ b/TelegramBotBase/Factories/LambdaFormFactory.cs @@ -1,4 +1,5 @@ -using TelegramBotBase.Form; +using System; +using TelegramBotBase.Form; using TelegramBotBase.Interfaces; namespace TelegramBotBase.Factories; @@ -8,14 +9,27 @@ public class LambdaFormFactory : IFormFactory public delegate FormBase CreateFormDelegate(); private readonly CreateFormDelegate _lambda; + + private readonly DefaultFormFactory _defaultFormFactory; public LambdaFormFactory(CreateFormDelegate lambda) { _lambda = lambda; + _defaultFormFactory = new DefaultFormFactory(lambda.GetType()); } public FormBase CreateStartForm() { return _lambda(); } + + public FormBase CreateForm(Type formType) + { + return _defaultFormFactory.CreateForm(formType); + } + + public FormBase CreateForm() where T : FormBase, new() + { + return CreateForm(typeof(T)); + } } \ No newline at end of file diff --git a/TelegramBotBase/Factories/ServiceProviderFormFactory.cs b/TelegramBotBase/Factories/ServiceProviderFormFactory.cs index 26c57ee..b6d9318 100644 --- a/TelegramBotBase/Factories/ServiceProviderFormFactory.cs +++ b/TelegramBotBase/Factories/ServiceProviderFormFactory.cs @@ -25,11 +25,21 @@ public ServiceProviderFormFactory(Type startFormClass, IServiceProvider serviceP public FormBase CreateStartForm() { + return CreateForm(_startFormClass); + } + + public FormBase CreateForm(Type formType) + { + if (!typeof(FormBase).IsAssignableFrom(formType)) + { + throw new ArgumentException($"{nameof(formType)} argument must be a {nameof(FormBase)} type"); + } + FormBase fb = null; try { - fb = (FormBase)ActivatorUtilities.CreateInstance(_serviceProvider, _startFormClass); + fb = (FormBase)ActivatorUtilities.CreateInstance(_serviceProvider, formType); } catch(InvalidOperationException ex) { @@ -41,6 +51,11 @@ public FormBase CreateStartForm() return fb; } + + public FormBase CreateForm() where T : FormBase, new() + { + return CreateForm(typeof(T)); + } } public class ServiceProviderFormFactory : ServiceProviderFormFactory From c936d823897767c6051d9bc08922fbe8e16a99bb Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 01:08:09 +0300 Subject: [PATCH 7/9] Refactor form instantiation in SessionManager Replaces direct constructor invocation with usage of BotBase.FormFactory.CreateForm for form instantiation. Adds additional null checks and ensures fallback form creation is attempted only if necessary. This improves flexibility and maintainability of form creation logic. --- TelegramBotBase/SessionManager.cs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/TelegramBotBase/SessionManager.cs b/TelegramBotBase/SessionManager.cs index e652074..f0fed62 100644 --- a/TelegramBotBase/SessionManager.cs +++ b/TelegramBotBase/SessionManager.cs @@ -146,27 +146,19 @@ public async Task LoadSessionStates(IStateMachine statemachine) continue; } - //No default constructor, fallback - if (!(t.GetConstructor(new Type[] { })?.Invoke(new object[] { }) is FormBase form)) - { - if (!statemachine.FallbackStateForm.IsSubclassOf(typeof(FormBase))) - { - continue; - } + var form = BotBase.FormFactory.CreateForm(t); - form = - statemachine.FallbackStateForm.GetConstructor(new Type[] { }) - ?.Invoke(new object[] { }) as FormBase; - - //Fallback failed, due missing default constructor - if (form == null) - { - continue; - } + if (form == null && statemachine.FallbackStateForm != null) + { + BotBase.FormFactory.CreateForm(statemachine.FallbackStateForm); } + if (form == null) + { + continue; + } - if (s.Values != null && s.Values.Count > 0) + if (t == form.GetType() && s.Values != null && s.Values.Count > 0) { var properties = s.Values.Where(a => a.Key.StartsWith("$")); var fields = form.GetType() From 2216ea17db7e5744635d782298424b993b5fefd3 Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 01:30:06 +0300 Subject: [PATCH 8/9] Remove new() constraint from CreateForm in IFormFactory The new() constraint was removed from the CreateForm method in IFormFactory and its implementations. This change allows for greater flexibility in form instantiation, enabling support for forms without parameterless constructors. DefaultFormFactory now throws an exception if a parameterless constructor is missing. --- TelegramBotBase/Factories/DefaultFormFactory.cs | 10 ++++++++-- TelegramBotBase/Factories/LambdaFormFactory.cs | 2 +- .../Factories/ServiceProviderFormFactory.cs | 2 +- TelegramBotBase/Interfaces/IFormFactory.cs | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/TelegramBotBase/Factories/DefaultFormFactory.cs b/TelegramBotBase/Factories/DefaultFormFactory.cs index 560d41c..c202568 100644 --- a/TelegramBotBase/Factories/DefaultFormFactory.cs +++ b/TelegramBotBase/Factories/DefaultFormFactory.cs @@ -31,10 +31,16 @@ public FormBase CreateForm(Type formType) throw new ArgumentException($"{nameof(formType)} argument must be a {nameof(FormBase)} type"); } - return formType.GetConstructor(new Type[] { })?.Invoke(new object[] { }) as FormBase; + // No parameterless constructor + if (!(formType.GetConstructor(new Type[] { })?.Invoke(new object[] { }) is FormBase form)) + { + throw new Exception($"{formType} must have a parameterless constructor."); + } + + return form; } - public FormBase CreateForm() where T : FormBase, new() + public FormBase CreateForm() where T : FormBase { return CreateForm(typeof(T)); } diff --git a/TelegramBotBase/Factories/LambdaFormFactory.cs b/TelegramBotBase/Factories/LambdaFormFactory.cs index 5992ed4..c1f8757 100644 --- a/TelegramBotBase/Factories/LambdaFormFactory.cs +++ b/TelegramBotBase/Factories/LambdaFormFactory.cs @@ -28,7 +28,7 @@ public FormBase CreateForm(Type formType) return _defaultFormFactory.CreateForm(formType); } - public FormBase CreateForm() where T : FormBase, new() + public FormBase CreateForm() where T : FormBase { return CreateForm(typeof(T)); } diff --git a/TelegramBotBase/Factories/ServiceProviderFormFactory.cs b/TelegramBotBase/Factories/ServiceProviderFormFactory.cs index b6d9318..bf3e7c1 100644 --- a/TelegramBotBase/Factories/ServiceProviderFormFactory.cs +++ b/TelegramBotBase/Factories/ServiceProviderFormFactory.cs @@ -52,7 +52,7 @@ public FormBase CreateForm(Type formType) return fb; } - public FormBase CreateForm() where T : FormBase, new() + public FormBase CreateForm() where T : FormBase { return CreateForm(typeof(T)); } diff --git a/TelegramBotBase/Interfaces/IFormFactory.cs b/TelegramBotBase/Interfaces/IFormFactory.cs index 48bf530..abb3186 100644 --- a/TelegramBotBase/Interfaces/IFormFactory.cs +++ b/TelegramBotBase/Interfaces/IFormFactory.cs @@ -7,5 +7,5 @@ public interface IFormFactory { FormBase CreateStartForm(); FormBase CreateForm(Type formType); - FormBase CreateForm() where T : FormBase, new(); + FormBase CreateForm() where T : FormBase; } \ No newline at end of file From 8877133340d8bfaa15936bf2e87098821ece6d42 Mon Sep 17 00:00:00 2001 From: Usevalad Buben Date: Sun, 5 Oct 2025 03:10:46 +0300 Subject: [PATCH 9/9] Fix missing assignment in fallback form creation Assign the created fallback form to the 'form' variable to ensure it is used when the initial form is null. --- TelegramBotBase/SessionManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TelegramBotBase/SessionManager.cs b/TelegramBotBase/SessionManager.cs index f0fed62..1cba95e 100644 --- a/TelegramBotBase/SessionManager.cs +++ b/TelegramBotBase/SessionManager.cs @@ -150,7 +150,7 @@ public async Task LoadSessionStates(IStateMachine statemachine) if (form == null && statemachine.FallbackStateForm != null) { - BotBase.FormFactory.CreateForm(statemachine.FallbackStateForm); + form = BotBase.FormFactory.CreateForm(statemachine.FallbackStateForm); } if (form == null)