From 237645033ccb0f47e914589b2a7e95365c12cdbc Mon Sep 17 00:00:00 2001 From: "LAPTOP-3CFGGVOS\\rabbit" Date: Tue, 11 Jun 2024 21:05:29 +0800 Subject: [PATCH] optimize BotSharpMessageParser --- .../BotSharp.Abstraction.csproj | 1 + .../Messaging/BotSharpMessageParser.cs | 101 +++++++++++------- .../Messaging/Enums/RichTypeEnum.cs | 1 + .../Template/ProductTemplateMessage.cs | 2 +- .../Models/RichContent/TextMessage.cs | 2 + 5 files changed, 70 insertions(+), 37 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj index 65424adb..b97758f1 100644 --- a/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj +++ b/src/Infrastructure/BotSharp.Abstraction/BotSharp.Abstraction.csproj @@ -19,6 +19,7 @@ + diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs index 1f495a44..483900a4 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/BotSharpMessageParser.cs @@ -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 GenericTemplateTypeMap = new(); + private static Dictionary ElementTypeMap = new(); + private static Dictionary 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; diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Enums/RichTypeEnum.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Enums/RichTypeEnum.cs index 7603f790..968aa30c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Enums/RichTypeEnum.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Enums/RichTypeEnum.cs @@ -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"; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ProductTemplateMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ProductTemplateMessage.cs index 05af097a..201131be 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ProductTemplateMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/Template/ProductTemplateMessage.cs @@ -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] diff --git a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs index 3a37ad54..966701bd 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Messaging/Models/RichContent/TextMessage.cs @@ -8,6 +8,8 @@ public class TextMessage : IRichMessage [Translate] public string Text { get; set; } = string.Empty; + public TextMessage() { } + public TextMessage(string text) { Text = text;