Migrate start form creation from generics to a factory method pattern

Add SimpleStartFormFactory.cs that encloses old behavior
This commit is contained in:
Victor 2021-10-11 14:23:27 +03:00
parent 7004ee5963
commit bab69b593e
5 changed files with 83 additions and 78 deletions

View File

@ -0,0 +1,25 @@
using System;
using Telegram.Bot.Exceptions;
using TelegramBotBase.Form;
using TelegramBotBase.Interfaces;
namespace TelegramBotBase.Base
{
public class SimpleStartFormFactory : IStartFormFactory
{
private readonly Type _startFormClass;
public SimpleStartFormFactory(Type startFormClass)
{
if (!typeof(FormBase).IsAssignableFrom(startFormClass))
throw new ArgumentException("startFormClass argument must be a FormBase type");
_startFormClass = startFormClass;
}
public FormBase CreateForm()
{
return _startFormClass.GetConstructor(new Type[] { })?.Invoke(new object[] { }) as FormBase;
}
}
}

View File

@ -20,8 +20,7 @@ namespace TelegramBotBase
/// Bot base class for full Device/Context and Messagehandling /// Bot base class for full Device/Context and Messagehandling
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public class BotBase<T> public class BotBase
where T : FormBase
{ {
public MessageClient Client { get; set; } public MessageClient Client { get; set; }
@ -33,7 +32,7 @@ namespace TelegramBotBase
/// <summary> /// <summary>
/// List of all running/active sessions /// List of all running/active sessions
/// </summary> /// </summary>
public SessionBase<T> Sessions { get; set; } public SessionBase Sessions { get; set; }
/// <summary> /// <summary>
/// Contains System commands which will be available at everytime and didnt get passed to forms, i.e. /start /// Contains System commands which will be available at everytime and didnt get passed to forms, i.e. /start
@ -68,7 +67,7 @@ namespace TelegramBotBase
public Dictionary<eSettings, uint> SystemSettings { get; private set; } public Dictionary<eSettings, uint> SystemSettings { get; private set; }
private BotBase() private BotBase(IStartFormFactory factory)
{ {
this.SystemSettings = new Dictionary<eSettings, uint>(); this.SystemSettings = new Dictionary<eSettings, uint>();
@ -80,7 +79,7 @@ namespace TelegramBotBase
this.BotCommands = new List<BotCommand>(); this.BotCommands = new List<BotCommand>();
this.Sessions = new SessionBase<T>(); this.Sessions = new SessionBase(factory);
this.Sessions.BotBase = this; this.Sessions.BotBase = this;
} }
@ -88,7 +87,10 @@ namespace TelegramBotBase
/// Simple start of your Bot with the APIKey /// Simple start of your Bot with the APIKey
/// </summary> /// </summary>
/// <param name="apiKey"></param> /// <param name="apiKey"></param>
public BotBase(String apiKey, bool initClient = true) : this() /// <param name="startFormFactory"></param>
/// <param name="initClient"></param>
public BotBase(String apiKey, IStartFormFactory startFormFactory, bool initClient = true)
: this(startFormFactory)
{ {
this.APIKey = apiKey; this.APIKey = apiKey;
@ -106,7 +108,8 @@ namespace TelegramBotBase
/// </summary> /// </summary>
/// <param name="apiKey"></param> /// <param name="apiKey"></param>
/// <param name="proxyBaseAddress">i.e. https://127.0.0.1:10000</param> /// <param name="proxyBaseAddress">i.e. https://127.0.0.1:10000</param>
public BotBase(String apiKey, System.Net.Http.HttpClient proxy) : this(apiKey, false) /// <param name="startFormFactory"></param>
public BotBase(String apiKey, IStartFormFactory startFormFactory, System.Net.Http.HttpClient proxy) : this(apiKey, startFormFactory, false)
{ {
this.Client = new Base.MessageClient(this.APIKey, proxy); this.Client = new Base.MessageClient(this.APIKey, proxy);
@ -117,8 +120,9 @@ namespace TelegramBotBase
/// Simple start of your Bot with the APIKey and a TelegramBotClient instance. /// Simple start of your Bot with the APIKey and a TelegramBotClient instance.
/// </summary> /// </summary>
/// <param name="apiKey"></param> /// <param name="apiKey"></param>
/// <param name="startFormFactory"></param>
/// <param name="client"></param> /// <param name="client"></param>
public BotBase(String apiKey, TelegramBotClient client) : this(apiKey, false) public BotBase(String apiKey, IStartFormFactory startFormFactory, TelegramBotClient client) : this(apiKey, startFormFactory, false)
{ {
this.Client = new Base.MessageClient(this.APIKey, client); this.Client = new Base.MessageClient(this.APIKey, client);
@ -129,8 +133,9 @@ namespace TelegramBotBase
/// Simple start of your Bot with the APIKey and a proxyAdress /// Simple start of your Bot with the APIKey and a proxyAdress
/// </summary> /// </summary>
/// <param name="apiKey"></param> /// <param name="apiKey"></param>
/// <param name="startFormFactory"></param>
/// <param name="proxyBaseAddress">i.e. https://127.0.0.1:10000</param> /// <param name="proxyBaseAddress">i.e. https://127.0.0.1:10000</param>
public BotBase(String apiKey, String proxyBaseAddress) : this(apiKey, false) public BotBase(String apiKey, IStartFormFactory startFormFactory, String proxyBaseAddress) : this(apiKey, startFormFactory, false)
{ {
var url = new Uri(proxyBaseAddress); var url = new Uri(proxyBaseAddress);
@ -143,9 +148,10 @@ namespace TelegramBotBase
/// Simple start of your Bot with the APIKey and a proxyAdress /// Simple start of your Bot with the APIKey and a proxyAdress
/// </summary> /// </summary>
/// <param name="apiKey"></param> /// <param name="apiKey"></param>
/// <param name="startFormFactory"></param>
/// <param name="proxyHost">i.e. 127.0.0.1</param> /// <param name="proxyHost">i.e. 127.0.0.1</param>
/// <param name="proxyPort">i.e. 10000</param> /// <param name="proxyPort">i.e. 10000</param>
public BotBase(String apiKey, String proxyHost, int proxyPort) : this(apiKey, false) public BotBase(String apiKey, IStartFormFactory startFormFactory, String proxyHost, int proxyPort) : this(apiKey, startFormFactory, false)
{ {
this.Client = new Base.MessageClient(this.APIKey, proxyHost, proxyPort); this.Client = new Base.MessageClient(this.APIKey, proxyHost, proxyPort);
@ -172,10 +178,7 @@ namespace TelegramBotBase
//Enable auto session saving //Enable auto session saving
if (this.GetSetting(eSettings.SaveSessionsOnConsoleExit, false)) if (this.GetSetting(eSettings.SaveSessionsOnConsoleExit, false))
{ {
TelegramBotBase.Tools.Console.SetHandler(() => TelegramBotBase.Tools.Console.SetHandler(() => { this.Sessions.SaveSessionStates(); });
{
this.Sessions.SaveSessionStates();
});
} }
DeviceSession.MaxNumberOfRetries = this.GetSetting(eSettings.MaxNumberOfRetries, 5); DeviceSession.MaxNumberOfRetries = this.GetSetting(eSettings.MaxNumberOfRetries, 5);
@ -237,7 +240,6 @@ namespace TelegramBotBase
} }
catch (Telegram.Bot.Exceptions.ApiRequestException ex) catch (Telegram.Bot.Exceptions.ApiRequestException ex)
{ {
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -247,7 +249,6 @@ namespace TelegramBotBase
} }
//private async Task Client_TryMessage(object sender, MessageResult e) //private async Task Client_TryMessage(object sender, MessageResult e)
//{ //{
// DeviceSession ds = e.Device; // DeviceSession ds = e.Device;
@ -324,7 +325,7 @@ namespace TelegramBotBase
DeviceSession ds = e.Device; DeviceSession ds = e.Device;
if (ds == null) if (ds == null)
{ {
ds = await this.Sessions.StartSession<T>(e.DeviceId); ds = await this.Sessions.StartSession(e.DeviceId);
e.Device = ds; e.Device = ds;
ds.LastMessage = e.Message; ds.LastMessage = e.Message;
@ -368,8 +369,12 @@ namespace TelegramBotBase
await activeForm.Load(e); await activeForm.Load(e);
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document) //Is Attachment ? (Photo, Audio, Video, Contact, Location, Document)
if (e.MessageType == Telegram.Bot.Types.Enums.MessageType.Contact | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Document | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Location | if (e.MessageType == Telegram.Bot.Types.Enums.MessageType.Contact |
e.MessageType == Telegram.Bot.Types.Enums.MessageType.Photo | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Video | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Audio) e.MessageType == Telegram.Bot.Types.Enums.MessageType.Document |
e.MessageType == Telegram.Bot.Types.Enums.MessageType.Location |
e.MessageType == Telegram.Bot.Types.Enums.MessageType.Photo |
e.MessageType == Telegram.Bot.Types.Enums.MessageType.Video |
e.MessageType == Telegram.Bot.Types.Enums.MessageType.Audio)
{ {
await activeForm.SentData(new DataResult(e)); await activeForm.SentData(new DataResult(e));
} }
@ -385,7 +390,8 @@ namespace TelegramBotBase
if (!e.Handled) if (!e.Handled)
{ {
var uhc = new UnhandledCallEventArgs(e.Message.Text, e.RawData, ds.DeviceId, e.MessageId, e.Message, ds); var uhc = new UnhandledCallEventArgs(e.Message.Text, e.RawData, ds.DeviceId, e.MessageId,
e.Message, ds);
OnUnhandledCall(uhc); OnUnhandledCall(uhc);
if (uhc.Handled) if (uhc.Handled)
@ -397,7 +403,6 @@ namespace TelegramBotBase
} }
} }
} }
} }
if (!ds.FormSwitched) if (!ds.FormSwitched)
@ -409,10 +414,7 @@ namespace TelegramBotBase
} }
e.IsFirstHandler = false; e.IsFirstHandler = false;
} while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10)); } while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10));
} }
/// <summary> /// <summary>
@ -469,7 +471,6 @@ namespace TelegramBotBase
} }
catch (Telegram.Bot.Exceptions.ApiRequestException ex) catch (Telegram.Bot.Exceptions.ApiRequestException ex)
{ {
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -483,7 +484,7 @@ namespace TelegramBotBase
DeviceSession ds = e.Device; DeviceSession ds = e.Device;
if (ds == null) if (ds == null)
{ {
ds = await this.Sessions.StartSession<T>(e.DeviceId); ds = await this.Sessions.StartSession(e.DeviceId);
e.Device = ds; e.Device = ds;
} }
@ -498,7 +499,6 @@ namespace TelegramBotBase
{ {
await Client_Loop(sender, e); await Client_Loop(sender, e);
} }
} }
private async void Client_Action(object sender, MessageResult e) private async void Client_Action(object sender, MessageResult e)
@ -658,23 +658,15 @@ namespace TelegramBotBase
/// <summary> /// <summary>
/// Will be called if a session/context gets started /// Will be called if a session/context gets started
/// </summary> /// </summary>
public event EventHandler<SessionBeginEventArgs> SessionBegins public event EventHandler<SessionBeginEventArgs> SessionBegins
{ {
add add { this.__Events.AddHandler(__evSessionBegins, value); }
{ remove { this.__Events.RemoveHandler(__evSessionBegins, value); }
this.__Events.AddHandler(__evSessionBegins, value);
}
remove
{
this.__Events.RemoveHandler(__evSessionBegins, value);
}
} }
public void OnSessionBegins(SessionBeginEventArgs e) public void OnSessionBegins(SessionBeginEventArgs e)
{ {
(this.__Events[__evSessionBegins] as EventHandler<SessionBeginEventArgs>)?.Invoke(this, e); (this.__Events[__evSessionBegins] as EventHandler<SessionBeginEventArgs>)?.Invoke(this, e);
} }
/// <summary> /// <summary>
@ -682,20 +674,13 @@ namespace TelegramBotBase
/// </summary> /// </summary>
public event EventHandler<MessageIncomeEventArgs> Message public event EventHandler<MessageIncomeEventArgs> Message
{ {
add add { this.__Events.AddHandler(__evMessage, value); }
{ remove { this.__Events.RemoveHandler(__evMessage, value); }
this.__Events.AddHandler(__evMessage, value);
}
remove
{
this.__Events.RemoveHandler(__evMessage, value);
}
} }
public void OnMessage(MessageIncomeEventArgs e) public void OnMessage(MessageIncomeEventArgs e)
{ {
(this.__Events[__evMessage] as EventHandler<MessageIncomeEventArgs>)?.Invoke(this, e); (this.__Events[__evMessage] as EventHandler<MessageIncomeEventArgs>)?.Invoke(this, e);
} }
/// <summary> /// <summary>
@ -715,20 +700,13 @@ namespace TelegramBotBase
/// </summary> /// </summary>
public event EventHandler<SystemExceptionEventArgs> Exception public event EventHandler<SystemExceptionEventArgs> Exception
{ {
add add { this.__Events.AddHandler(__evException, value); }
{ remove { this.__Events.RemoveHandler(__evException, value); }
this.__Events.AddHandler(__evException, value);
}
remove
{
this.__Events.RemoveHandler(__evException, value);
}
} }
public void OnException(SystemExceptionEventArgs e) public void OnException(SystemExceptionEventArgs e)
{ {
(this.__Events[__evException] as EventHandler<SystemExceptionEventArgs>)?.Invoke(this, e); (this.__Events[__evException] as EventHandler<SystemExceptionEventArgs>)?.Invoke(this, e);
} }
/// <summary> /// <summary>
@ -736,23 +714,15 @@ namespace TelegramBotBase
/// </summary> /// </summary>
public event EventHandler<UnhandledCallEventArgs> UnhandledCall public event EventHandler<UnhandledCallEventArgs> UnhandledCall
{ {
add add { this.__Events.AddHandler(__evUnhandledCall, value); }
{ remove { this.__Events.RemoveHandler(__evUnhandledCall, value); }
this.__Events.AddHandler(__evUnhandledCall, value);
}
remove
{
this.__Events.RemoveHandler(__evUnhandledCall, value);
}
} }
public void OnUnhandledCall(UnhandledCallEventArgs e) public void OnUnhandledCall(UnhandledCallEventArgs e)
{ {
(this.__Events[__evUnhandledCall] as EventHandler<UnhandledCallEventArgs>)?.Invoke(this, e); (this.__Events[__evUnhandledCall] as EventHandler<UnhandledCallEventArgs>)?.Invoke(this, e);
} }
#endregion #endregion
} }
} }

View File

@ -0,0 +1,9 @@
using TelegramBotBase.Form;
namespace TelegramBotBase.Interfaces
{
public interface IStartFormFactory
{
FormBase CreateForm();
}
}

View File

@ -16,18 +16,19 @@ namespace TelegramBotBase
/// <summary> /// <summary>
/// Base class for managing all active sessions /// Base class for managing all active sessions
/// </summary> /// </summary>
public class SessionBase<T> public class SessionBase
where T : FormBase
{ {
public MessageClient Client { get; set; } public MessageClient Client { get; set; }
public Dictionary<long, DeviceSession> SessionList { get; set; } public Dictionary<long, DeviceSession> SessionList { get; set; }
public BotBase<T> BotBase { get; set; } public BotBase BotBase { get; set; }
public IStartFormFactory StartFormFactory { get; set; }
public SessionBase() public SessionBase(IStartFormFactory startFormFactory)
{ {
StartFormFactory = startFormFactory;
this.SessionList = new Dictionary<long, DeviceSession>(); this.SessionList = new Dictionary<long, DeviceSession>();
} }
@ -65,19 +66,18 @@ namespace TelegramBotBase
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="deviceId"></param> /// <param name="deviceId"></param>
/// <returns></returns> /// <returns></returns>
public async Task<DeviceSession> StartSession<T>(long deviceId) public async Task<DeviceSession> StartSession(long deviceId)
where T : FormBase
{ {
T start = typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { }) as T; var start = StartFormFactory.CreateForm();
start.Client = this.Client; start.Client = Client;
DeviceSession ds = new Sessions.DeviceSession(deviceId, start); var ds = new DeviceSession(deviceId, start);
start.Device = ds; start.Device = ds;
await start.OnInit(new InitEventArgs()); await start.OnInit(new InitEventArgs());
await start.OnOpened(new EventArgs()); await start.OnOpened(EventArgs.Empty);
this[deviceId] = ds; this[deviceId] = ds;
return ds; return ds;

View File

@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot.Types; using Telegram.Bot.Types;
using TelegramBotBase; using TelegramBotBase;
using TelegramBotBase.Base;
using TelegramBotBase.Form; using TelegramBotBase.Form;
using TelegramBotBaseTest.Tests; using TelegramBotBaseTest.Tests;
using TelegramBotBase.Commands; using TelegramBotBase.Commands;
@ -15,7 +16,7 @@ namespace TelegramBotBaseTest
static void Main(string[] args) static void Main(string[] args)
{ {
BotBase<Start> bb = new BotBase<Start>(APIKey); BotBase bb = new BotBase(APIKey, new SimpleStartFormFactory(typeof(Start)));
bb.BotCommands.AddStartCommand("Starts the bot"); bb.BotCommands.AddStartCommand("Starts the bot");
bb.BotCommands.AddHelpCommand("Should show you some help"); bb.BotCommands.AddHelpCommand("Should show you some help");