Adding full DI navigation example for testing purposes.
- adding internal private field into FormBase class - adding Extension methods into DependencyInjection namespace for use - adding 2 NavigateTo extension methods for DI using ServiceProvider - adding example project - adding to readme as example
This commit is contained in:
parent
e6a48115a6
commit
30222d640d
12
Examples/DependencyInjection/Database/BotDbContext.cs
Normal file
12
Examples/DependencyInjection/Database/BotDbContext.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DependencyInjection.Database;
|
||||
|
||||
public class BotDbContext : DbContext
|
||||
{
|
||||
public BotDbContext(DbContextOptions options) : base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public DbSet<User> Users { get; set; }
|
||||
}
|
||||
7
Examples/DependencyInjection/Database/User.cs
Normal file
7
Examples/DependencyInjection/Database/User.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace DependencyInjection.Database;
|
||||
|
||||
public class User
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string LastMessage { get; set; }
|
||||
}
|
||||
67
Examples/DependencyInjection/Forms/ConfirmationForm.cs
Normal file
67
Examples/DependencyInjection/Forms/ConfirmationForm.cs
Normal file
@ -0,0 +1,67 @@
|
||||
using DependencyInjection.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TelegramBotBase.Base;
|
||||
using TelegramBotBase.Form;
|
||||
using TelegramBotBase.DependencyInjection;
|
||||
|
||||
namespace DependencyInjection.Forms
|
||||
{
|
||||
public class ConfirmationForm : FormBase
|
||||
{
|
||||
private readonly BotDbContext _dbContext;
|
||||
|
||||
public ConfirmationForm(BotDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public override async Task Load(MessageResult message)
|
||||
{
|
||||
var user = await _dbContext.Users.FindAsync(Device.DeviceId);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
await this.NavigateTo<StartForm>();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task Action(MessageResult message)
|
||||
{
|
||||
await message.ConfirmAction("Go back");
|
||||
|
||||
switch (message.RawData)
|
||||
{
|
||||
|
||||
case "back":
|
||||
|
||||
await this.NavigateTo<StartForm>();
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override async Task Render(MessageResult message)
|
||||
{
|
||||
var user = await _dbContext.Users.FindAsync(Device.DeviceId);
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
var bf = new ButtonForm();
|
||||
bf.AddButtonRow("Back", "back");
|
||||
|
||||
await Device.Send($"ConfirmationForm: Your last message was: {user.LastMessage}. Click \"Back\" to get back.", bf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
79
Examples/DependencyInjection/StartForm.cs
Normal file
79
Examples/DependencyInjection/StartForm.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using DependencyInjection.Database;
|
||||
using DependencyInjection.Forms;
|
||||
using TelegramBotBase.Base;
|
||||
using TelegramBotBase.Form;
|
||||
using TelegramBotBase.DependencyInjection;
|
||||
|
||||
namespace DependencyInjection;
|
||||
|
||||
public class StartForm : FormBase
|
||||
{
|
||||
private readonly BotDbContext _dbContext;
|
||||
|
||||
public StartForm(BotDbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public override async Task Load(MessageResult message)
|
||||
{
|
||||
var user = await _dbContext.Users.FindAsync(Device.DeviceId);
|
||||
if (user is null)
|
||||
{
|
||||
user = new User
|
||||
{
|
||||
Id = Device.DeviceId,
|
||||
LastMessage = "<unknown>"
|
||||
};
|
||||
|
||||
_dbContext.Users.Add(user);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (message.IsAction)
|
||||
return;
|
||||
|
||||
|
||||
user.LastMessage = string.IsNullOrWhiteSpace(message.MessageText) ? "<unknown>" : message.MessageText;
|
||||
await _dbContext.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public override async Task Action(MessageResult message)
|
||||
{
|
||||
await message.ConfirmAction("Ok");
|
||||
|
||||
switch(message.RawData)
|
||||
{
|
||||
|
||||
case "open":
|
||||
|
||||
await this.NavigateTo(typeof(ConfirmationForm));
|
||||
|
||||
var new_form = await this.NavigateTo<ConfirmationForm>();
|
||||
|
||||
if (new_form == null)
|
||||
{
|
||||
await Device.Send("Cant open ConfirmationForm");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override async Task Render(MessageResult message)
|
||||
{
|
||||
var user = await _dbContext.Users.FindAsync(Device.DeviceId);
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
var bf = new ButtonForm();
|
||||
|
||||
bf.AddButtonRow("Open confirmation", "open");
|
||||
|
||||
await Device.Send($"Your last message's text was: `{user.LastMessage}`", bf);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1072,3 +1072,8 @@ Having already a web application and want to add a TelegramBot side-by-side with
|
||||
Want to use Inline- and ReplyMarkup at the same time ? Here is an example how you can do that:
|
||||
|
||||
- [Examples/InlineAndReplyCombination](Examples/InlineAndReplyCombination)
|
||||
|
||||
|
||||
Alpha: Full Dependency Injection example within this framework.
|
||||
|
||||
- [Examples/DependencyInjection](Examples/DependencyInjection)
|
||||
@ -32,6 +32,8 @@ public class FormBase : IDisposable
|
||||
|
||||
public MessageClient Client { get; set; }
|
||||
|
||||
IServiceProvider _serviceProvider = null;
|
||||
|
||||
/// <summary>
|
||||
/// has this formular already been disposed ?
|
||||
/// </summary>
|
||||
|
||||
86
TelegramBotBase/DependencyInjection/Extensions.cs
Normal file
86
TelegramBotBase/DependencyInjection/Extensions.cs
Normal file
@ -0,0 +1,86 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TelegramBotBase.Form;
|
||||
|
||||
namespace TelegramBotBase.DependencyInjection
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
internal static FieldInfo _ServiceProviderField = typeof(FormBase).GetField("_serviceProvider", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
|
||||
|
||||
/// <summary>
|
||||
/// Use Dependency Injection to create new form and inject parameters. (Main variant)
|
||||
/// </summary>
|
||||
/// <typeparam name="NewForm"></typeparam>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<NewForm> NavigateTo<NewForm>(this FormBase current_form, params object[] args)
|
||||
where NewForm : FormBase
|
||||
{
|
||||
var _serviceProvider = current_form.GetServiceProvider();
|
||||
|
||||
var instance = ActivatorUtilities.CreateInstance(_serviceProvider, typeof(NewForm)) as NewForm;
|
||||
|
||||
if (instance == null)
|
||||
return null; //throw new Exception("Could not instantiate new form via DI.");
|
||||
|
||||
instance.SetServiceProvider(_serviceProvider);
|
||||
|
||||
await current_form.NavigateTo(instance, args);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use Dependency Injection to create new form and inject parameters. (Alternative variant)
|
||||
/// </summary>
|
||||
/// <param name="current_form"></param>
|
||||
/// <param name="formBaseType"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public static async Task<FormBase> NavigateTo(this FormBase current_form, Type formBaseType, params object[] args)
|
||||
{
|
||||
if (!typeof(FormBase).IsAssignableFrom(formBaseType))
|
||||
throw new ArgumentException($"{nameof(formBaseType)} argument must be a {nameof(FormBase)} type");
|
||||
|
||||
var _serviceProvider = current_form.GetServiceProvider();
|
||||
|
||||
var instance = ActivatorUtilities.CreateInstance(_serviceProvider, formBaseType) as FormBase;
|
||||
|
||||
if (instance == null)
|
||||
return null; //throw new Exception("Could not instantiate new form via DI.");
|
||||
|
||||
instance.SetServiceProvider(_serviceProvider);
|
||||
|
||||
await current_form.NavigateTo(instance, args);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the internal service provider field.
|
||||
/// </summary>
|
||||
/// <param name="form"></param>
|
||||
/// <param name="serviceProvider"></param>
|
||||
public static void SetServiceProvider(this FormBase form, IServiceProvider serviceProvider)
|
||||
{
|
||||
_ServiceProviderField?.SetValue(form, serviceProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the internal service provider field value.
|
||||
/// </summary>
|
||||
/// <param name="form"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceProvider GetServiceProvider(this FormBase form)
|
||||
{
|
||||
var sp = _ServiceProviderField?.GetValue(form) as IServiceProvider;
|
||||
return sp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TelegramBotBase.DependencyInjection;
|
||||
using TelegramBotBase.Form;
|
||||
using TelegramBotBase.Interfaces;
|
||||
|
||||
@ -16,14 +17,19 @@ public class ServiceProviderStartFormFactory : IStartFormFactory
|
||||
{
|
||||
throw new ArgumentException($"{nameof(startFormClass)} argument must be a {nameof(FormBase)} type");
|
||||
}
|
||||
|
||||
|
||||
_startFormClass = startFormClass;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public FormBase CreateForm()
|
||||
{
|
||||
return (FormBase)ActivatorUtilities.CreateInstance(_serviceProvider, _startFormClass);
|
||||
var fb = (FormBase)ActivatorUtilities.CreateInstance(_serviceProvider, _startFormClass);
|
||||
|
||||
//Sets an internal field for future ServiceProvider navigation
|
||||
fb.SetServiceProvider(_serviceProvider);
|
||||
|
||||
return fb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user