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
/// </summary>
/// <typeparam name="T"></typeparam>
public class BotBase<T>
where T : FormBase
public class BotBase
{
public MessageClient Client { get; set; }
@ -33,7 +32,7 @@ namespace TelegramBotBase
/// <summary>
/// List of all running/active sessions
/// </summary>
public SessionBase<T> Sessions { get; set; }
public SessionBase Sessions { get; set; }
/// <summary>
/// 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; }
private BotBase()
private BotBase(IStartFormFactory factory)
{
this.SystemSettings = new Dictionary<eSettings, uint>();
@ -80,7 +79,7 @@ namespace TelegramBotBase
this.BotCommands = new List<BotCommand>();
this.Sessions = new SessionBase<T>();
this.Sessions = new SessionBase(factory);
this.Sessions.BotBase = this;
}
@ -88,7 +87,10 @@ namespace TelegramBotBase
/// Simple start of your Bot with the APIKey
/// </summary>
/// <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;
@ -106,7 +108,8 @@ namespace TelegramBotBase
/// </summary>
/// <param name="apiKey"></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);
@ -117,8 +120,9 @@ namespace TelegramBotBase
/// Simple start of your Bot with the APIKey and a TelegramBotClient instance.
/// </summary>
/// <param name="apiKey"></param>
/// <param name="startFormFactory"></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);
@ -129,8 +133,9 @@ namespace TelegramBotBase
/// Simple start of your Bot with the APIKey and a proxyAdress
/// </summary>
/// <param name="apiKey"></param>
/// <param name="startFormFactory"></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);
@ -143,9 +148,10 @@ namespace TelegramBotBase
/// Simple start of your Bot with the APIKey and a proxyAdress
/// </summary>
/// <param name="apiKey"></param>
/// <param name="startFormFactory"></param>
/// <param name="proxyHost">i.e. 127.0.0.1</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);
@ -172,10 +178,7 @@ namespace TelegramBotBase
//Enable auto session saving
if (this.GetSetting(eSettings.SaveSessionsOnConsoleExit, false))
{
TelegramBotBase.Tools.Console.SetHandler(() =>
{
this.Sessions.SaveSessionStates();
});
TelegramBotBase.Tools.Console.SetHandler(() => { this.Sessions.SaveSessionStates(); });
}
DeviceSession.MaxNumberOfRetries = this.GetSetting(eSettings.MaxNumberOfRetries, 5);
@ -237,7 +240,6 @@ namespace TelegramBotBase
}
catch (Telegram.Bot.Exceptions.ApiRequestException ex)
{
}
catch (Exception ex)
{
@ -247,7 +249,6 @@ namespace TelegramBotBase
}
//private async Task Client_TryMessage(object sender, MessageResult e)
//{
// DeviceSession ds = e.Device;
@ -324,7 +325,7 @@ namespace TelegramBotBase
DeviceSession ds = e.Device;
if (ds == null)
{
ds = await this.Sessions.StartSession<T>(e.DeviceId);
ds = await this.Sessions.StartSession(e.DeviceId);
e.Device = ds;
ds.LastMessage = e.Message;
@ -368,8 +369,12 @@ namespace TelegramBotBase
await activeForm.Load(e);
//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 |
e.MessageType == Telegram.Bot.Types.Enums.MessageType.Photo | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Video | e.MessageType == Telegram.Bot.Types.Enums.MessageType.Audio)
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 |
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));
}
@ -385,7 +390,8 @@ namespace TelegramBotBase
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);
if (uhc.Handled)
@ -397,7 +403,6 @@ namespace TelegramBotBase
}
}
}
}
if (!ds.FormSwitched)
@ -409,10 +414,7 @@ namespace TelegramBotBase
}
e.IsFirstHandler = false;
} while (ds.FormSwitched && i < this.GetSetting(eSettings.NavigationMaximum, 10));
}
/// <summary>
@ -469,7 +471,6 @@ namespace TelegramBotBase
}
catch (Telegram.Bot.Exceptions.ApiRequestException ex)
{
}
catch (Exception ex)
{
@ -483,7 +484,7 @@ namespace TelegramBotBase
DeviceSession ds = e.Device;
if (ds == null)
{
ds = await this.Sessions.StartSession<T>(e.DeviceId);
ds = await this.Sessions.StartSession(e.DeviceId);
e.Device = ds;
}
@ -498,7 +499,6 @@ namespace TelegramBotBase
{
await Client_Loop(sender, e);
}
}
private async void Client_Action(object sender, MessageResult e)
@ -658,23 +658,15 @@ namespace TelegramBotBase
/// <summary>
/// Will be called if a session/context gets started
/// </summary>
public event EventHandler<SessionBeginEventArgs> SessionBegins
{
add
{
this.__Events.AddHandler(__evSessionBegins, value);
}
remove
{
this.__Events.RemoveHandler(__evSessionBegins, value);
}
add { this.__Events.AddHandler(__evSessionBegins, value); }
remove { this.__Events.RemoveHandler(__evSessionBegins, value); }
}
public void OnSessionBegins(SessionBeginEventArgs e)
{
(this.__Events[__evSessionBegins] as EventHandler<SessionBeginEventArgs>)?.Invoke(this, e);
}
/// <summary>
@ -682,20 +674,13 @@ namespace TelegramBotBase
/// </summary>
public event EventHandler<MessageIncomeEventArgs> Message
{
add
{
this.__Events.AddHandler(__evMessage, value);
}
remove
{
this.__Events.RemoveHandler(__evMessage, value);
}
add { this.__Events.AddHandler(__evMessage, value); }
remove { this.__Events.RemoveHandler(__evMessage, value); }
}
public void OnMessage(MessageIncomeEventArgs e)
{
(this.__Events[__evMessage] as EventHandler<MessageIncomeEventArgs>)?.Invoke(this, e);
}
/// <summary>
@ -715,20 +700,13 @@ namespace TelegramBotBase
/// </summary>
public event EventHandler<SystemExceptionEventArgs> Exception
{
add
{
this.__Events.AddHandler(__evException, value);
}
remove
{
this.__Events.RemoveHandler(__evException, value);
}
add { this.__Events.AddHandler(__evException, value); }
remove { this.__Events.RemoveHandler(__evException, value); }
}
public void OnException(SystemExceptionEventArgs e)
{
(this.__Events[__evException] as EventHandler<SystemExceptionEventArgs>)?.Invoke(this, e);
}
/// <summary>
@ -736,23 +714,15 @@ namespace TelegramBotBase
/// </summary>
public event EventHandler<UnhandledCallEventArgs> UnhandledCall
{
add
{
this.__Events.AddHandler(__evUnhandledCall, value);
}
remove
{
this.__Events.RemoveHandler(__evUnhandledCall, value);
}
add { this.__Events.AddHandler(__evUnhandledCall, value); }
remove { this.__Events.RemoveHandler(__evUnhandledCall, value); }
}
public void OnUnhandledCall(UnhandledCallEventArgs e)
{
(this.__Events[__evUnhandledCall] as EventHandler<UnhandledCallEventArgs>)?.Invoke(this, e);
}
#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>
/// Base class for managing all active sessions
/// </summary>
public class SessionBase<T>
where T : FormBase
public class SessionBase
{
public MessageClient Client { 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>();
}
@ -65,19 +66,18 @@ namespace TelegramBotBase
/// <typeparam name="T"></typeparam>
/// <param name="deviceId"></param>
/// <returns></returns>
public async Task<DeviceSession> StartSession<T>(long deviceId)
where T : FormBase
public async Task<DeviceSession> StartSession(long deviceId)
{
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;
await start.OnInit(new InitEventArgs());
await start.OnOpened(new EventArgs());
await start.OnOpened(EventArgs.Empty);
this[deviceId] = ds;
return ds;

View File

@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using TelegramBotBase;
using TelegramBotBase.Base;
using TelegramBotBase.Form;
using TelegramBotBaseTest.Tests;
using TelegramBotBase.Commands;
@ -15,7 +16,7 @@ namespace TelegramBotBaseTest
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.AddHelpCommand("Should show you some help");