optimize BotSharpMessageParser

This commit is contained in:
LAPTOP-3CFGGVOS\rabbit 2024-06-11 21:05:29 +08:00
parent f3bdc73a4a
commit 237645033c
5 changed files with 70 additions and 37 deletions

View file

@ -19,6 +19,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />

View file

@ -2,57 +2,53 @@ using BotSharp.Abstraction.Messaging.Models.RichContent.Template;
using BotSharp.Abstraction.Messaging.Models.RichContent;
using System.Text.Json;
using System.Reflection;
using System.Linq;
namespace BotSharp.Abstraction.Messaging;
public static class BotSharpMessageParser
{
private static Dictionary<string, Type> GenericTemplateTypeMap = new();
private static Dictionary<string, Type> ElementTypeMap = new();
private static Dictionary<string, Type> NonGenericTemplateTypeMap = new();
static BotSharpMessageParser()
{
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.ToList();
ElementTypeMap = types
.Where(type => type.Name.EndsWith("Element"))
.ToDictionary(k => k.Name, v => v);
var richMessageTypes = types
.Where(type => typeof(IRichMessage).IsAssignableFrom(type) && !type.IsInterface && !type.IsAbstract)
.ToDictionary(k => GetRichTypeValue(k), v => v);
GenericTemplateTypeMap = richMessageTypes.Where(p => p.Value.IsGenericType).ToDictionary(k => k.Key, v => v.Value);
NonGenericTemplateTypeMap = richMessageTypes.Where(p => !p.Value.IsGenericType).ToDictionary(k => k.Key, v => v.Value);
}
public static IRichMessage? ParseRichMessage(JsonElement root, JsonSerializerOptions options)
{
IRichMessage? res = null;
Type? targetType = null;
JsonElement element;
var jsonText = root.GetRawText();
if (root.TryGetProperty("rich_type", out element))
{
var richType = element.GetString();
if (richType == RichTypeEnum.ButtonTemplate)
{
targetType = typeof(ButtonTemplateMessage);
}
else if (richType == RichTypeEnum.MultiSelectTemplate)
{
targetType = typeof(MultiSelectTemplateMessage);
}
else if (richType == RichTypeEnum.QuickReply)
{
targetType = typeof(QuickReplyMessage);
}
else if (richType == RichTypeEnum.CouponTemplate)
{
targetType = typeof(CouponTemplateMessage);
}
else if (richType == RichTypeEnum.Text)
{
targetType = typeof(TextMessage);
}
else if (richType == RichTypeEnum.GenericTemplate)
{
if (root.TryGetProperty("element_type", out element))
{
var elementType = element.GetString();
var wrapperType = typeof(GenericTemplateMessage<>);
var genericType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == elementType);
if (!root.TryGetProperty("rich_type", out var richTypeElement)) return res;
if (wrapperType != null && genericType != null)
{
targetType = wrapperType.MakeGenericType(genericType);
}
}
string? richType = richTypeElement.GetString();
if (GenericTemplateTypeMap.TryGetValue(richType, out var wrapperType))
{
if (root.TryGetProperty("element_type", out var elementTypeElement))
{
string? elementType = elementTypeElement.GetString();
targetType = CreateGenericElementType(wrapperType, elementType);
}
}
else if (NonGenericTemplateTypeMap.TryGetValue(richType, out targetType))
{
// targetType is already set by the dictionary lookup
}
if (targetType != null)
{
@ -62,6 +58,39 @@ public static class BotSharpMessageParser
return res;
}
private static Type? CreateGenericElementType(Type wrapperType, string elementTypeName)
{
if (wrapperType != null && ElementTypeMap.TryGetValue(elementTypeName, out var elementType))
{
return wrapperType.MakeGenericType(elementType);
}
return null;
}
private static string GetRichTypeValue(Type type)
{
var richTypeProperty = type.GetProperty("RichType", BindingFlags.Public | BindingFlags.Instance);
if (richTypeProperty != null && richTypeProperty.PropertyType == typeof(string))
{
return CreateRichMessage(type)?.RichType;
}
return null;
}
private static dynamic CreateRichMessage(Type type)
{
if (!type.IsGenericType)
{
return Activator.CreateInstance(type);
}
else
{
var genericType = type.MakeGenericType(typeof(object));
return Activator.CreateInstance(genericType);
}
}
public static ITemplateMessage? ParseTemplateMessage(JsonElement root, JsonSerializerOptions options)
{
ITemplateMessage? res = null;

View file

@ -9,4 +9,5 @@ public static class RichTypeEnum
public const string QuickReply = "quick_reply";
public const string Text = "text";
public const string Attachment = "attachment";
public const string ProductTemplate = "product_template";
}

View file

@ -3,7 +3,7 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent.Template;
public class ProductTemplateMessage : IRichMessage, ITemplateMessage
{
[JsonPropertyName("rich_type")]
public string RichType => RichTypeEnum.GenericTemplate;
public string RichType => RichTypeEnum.ProductTemplate;
[JsonPropertyName("text")]
[Translate]

View file

@ -8,6 +8,8 @@ public class TextMessage : IRichMessage
[Translate]
public string Text { get; set; } = string.Empty;
public TextMessage() { }
public TextMessage(string text)
{
Text = text;