一个包含动态变量的短信模板设计分析

简介:

我们在日常接触到的一些软件界面,往往喜欢深入分析其实现机理,通过学习、分析,可以提高我们对软件架构的分析能力,从而实现更加弹性、可重用的模块。在无意间,看到一个短信模块的设计,模板里面可以包含了很多变量,从而引发我对其深入分析的兴趣,本文主要介绍我对这些实现的一些理解,介绍一个包含动态变量的短信模板的设计分析。

1、短信模板的效果介绍

如下图所示,上面包含了短信模板的列表信息,以及对具体模板的内容设计,可以在其中插入变量的处理。

如果是硬编码对个别的实现应该很容易,如果我们考虑可扩展性、重用性等因素,需要进行弹性的设计,那么就需要寻找好的思路来动态处理这些变量了。

如它的每个模板的变量都是可以不同的,如其中一个模板有如下变量可以插入到模板内容里面,变量本身用左右的括弧{}进行标识,还是很有规律的。

2、短信模板的设计分析

由于模板是针对某个企业的,企业可能根据需要进行一定的调整,模板可以恢复为最初的版本,因此我们可以考虑设计两个部分,一个部分是基础模板,一个部分是对企业的消息模板,前者不变,后者可以根据需要修改,如无修改保存的,则采用对应的基础模板,也就是模板的模板了。

由于模板是包含有不同变量的,因此我们需要在设计的时候,动态解析这些变量。我们如果能够把传入的对象动态获取它的属性,并给对应的变量赋值,应该就可以实现这个功能。

那么我们就需要通过反射方式,动态获取对应object对象的各种属性名称和值了,这个处理操作如下所示。

        /// <summary>
        /// 把object对象的属性反射获取到字典列表中
        /// </summary>
        /// <param name="data">object对象</param>
        /// <returns></returns>
        public static Dictionary<string, string> GetProperties(object data)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();

            Type type = data.GetType();
            string[] propertyNames = type.GetProperties().Select(p => p.Name).ToArray();
            foreach (var prop in propertyNames)
            {
                object propValue = type.GetProperty(prop).GetValue(data, null);
                string value = (propValue != null) ? propValue.ToString() : "";
                if(!dict.ContainsKey(prop))
                {
                    dict.Add(prop, value);
                }
            }
            return dict;
        }    

前面介绍了,模板的内容,是包含有左右括弧{}的变量的,因此我们可以通过正则表达式,把它们提取出来备用,这样我们就可以把前面反射对应属性的值赋值给模板内容,从而形成新的待发送的具体消息了。

            var regex = @"\{(?<name>.*?)\}";
            List<string> itemList = GetList(template, regex, "name");

其中GetList就是一个正则表达式获取对应正则内容的函数,函数代码如下所示。

        /// <summary>
        /// 多个匹配内容
        /// </summary>
        /// <param name="sInput">输入内容</param>
        /// <param name="sRegex">表达式字符串</param>
        /// <param name="sGroupName">分组名, ""代表不分组</param>
        public static List<string> GetList(string sInput, string sRegex, string sGroupName)
        {
            List<string> list = new List<string>();
            Regex re = new Regex(sRegex, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);
            MatchCollection mcs = re.Matches(sInput);
            foreach (Match mc in mcs)
            {
                if (sGroupName != "")
                {
                    list.Add(mc.Groups[sGroupName].Value);
                }
                else
                {
                    list.Add(mc.Value);
                }
            }
            return list;
        }

最后我们可以把内容对应上,给模板替换为最新的属性值了。

        private void button1_Click(object sender, EventArgs e)
        {
            //模板文本
            var template = "姓名 = {姓名}, 性别 = {性别}, 卡号 = {卡号}, 公司 = {公司}";
            //数据对象
            var data = new { 姓名 = "伍华聪", 性别 = "", 卡号 = "10000", 公司 = "广州爱奇迪软件科技有限公司" };

            ReplaceTemplate(template, data);
        }

        private void ReplaceTemplate(string template, object data)
        {
            var regex = @"\{(?<name>.*?)\}";
            List<string> itemList = GetList(template, regex, "name");
                
            Console.WriteLine("列出模板变量对象:");
            foreach(string item in itemList)
            {
                Console.WriteLine(item);
            }

            Dictionary<string, string> dict = GetProperties(data);
            foreach(string item in itemList)
            {
                //如果属性存在,则替换模板,并修改模板值
                if(dict.ContainsKey(item))
                {
                    template = Replace(template, regex, dict.Values.ToList());//替换第一个
                }
            }

            Console.WriteLine(template);
        }

测试上面的代码,我们注意到我们的对象是动态构建的,也就是使用匿名类的方式构建一个类,包含有对应的属性值,把这个给模板进行解析,从而赋值形成真正的消息内容的。

var data = new { 姓名 = "伍华聪", 性别 = "", 卡号 = "10000", 公司 = "广州爱奇迪软件科技有限公司" };

测试案例,我们可以得到的消息,如下所示。

我们从上面截图可以看到,真正的消息已经正确得到,这些是替换具体的模板内容形成的,如果我们在整体的模板设计里面,采用这个思路,就可以实现动态的模板消息发送,从而实现了比较弹性化的设计处理。

本文只是对模板变量这种场景进行了分析,我们在实际项目中,可以更加完善,实现更加强大的模板消息处理,以及利用微信模板消息进行一起发送,实现短信、微信,甚至邮件的同步通知,给客户更好的体验。

 

以上是微信的模板消息介绍,我们也可以结合动态变量,把对应模板消息替换为我们要发送的消息,从而也实现了微信消息的动态发送。

本文转自博客园伍华聪的博客,原文链接:一个包含动态变量的短信模板设计分析,如需转载请自行联系原博主。



目录
相关文章
|
SQL 关系型数据库 MySQL
Python 数据库访问与ORM框架——打造高效开发利器
Python 作为一门广泛使用的编程语言,其在数据库访问方面也有着较为成熟的解决方案,其中ORM框架更是成为了开发者们的首选。本文将介绍 Python 中数据库访问和 ORM 框架的基本概念,以及如何使用 SQLAlchemy 这一优秀的 ORM 框架进行开发。
|
存储 关系型数据库 MySQL
云计算|OpenStack|社区版OpenStack安装部署文档(四 --- 镜像服务glance安装部署---Rocky版)
云计算|OpenStack|社区版OpenStack安装部署文档(四 --- 镜像服务glance安装部署---Rocky版)
398 0
|
11月前
|
存储 人工智能 自然语言处理
AI经营|多Agent择优生成商品标题
商品标题中关键词的好坏是商品能否被主搜检索到的关键因素,使用大模型自动优化标题成为【AI经营】中的核心能力之一,本文讲述大模型如何帮助商家优化商品素材,提升商品竞争力。
1191 62
AI经营|多Agent择优生成商品标题
|
11月前
|
Python
Python三引号用法与变量详解
本文详细介绍了Python中三引号(`&quot;&quot;&quot;` 或 `&#39;&#39;&#39;`)的用法,包括其基本功能、如何在多行字符串中使用变量(如f-string、str.format()和%操作符),以及实际应用示例,帮助读者更好地理解和运用这一强大工具。
983 2
|
Docker 容器
Docker部署minio-arm64版本,阿里官方推荐
Docker部署minio-arm64版本,阿里官方推荐
|
SQL 数据库
SQL DELETE 语句
【7月更文挑战第12天】SQL DELETE 语句。
233 10
|
缓存 Linux C语言
C语言 多进程编程(六)共享内存
本文介绍了Linux系统下的多进程通信机制——共享内存的使用方法。首先详细讲解了如何通过`shmget()`函数创建共享内存,并提供了示例代码。接着介绍了如何利用`shmctl()`函数删除共享内存。随后,文章解释了共享内存映射的概念及其实现方法,包括使用`shmat()`函数进行映射以及使用`shmdt()`函数解除映射,并给出了相应的示例代码。最后,展示了如何在共享内存中读写数据的具体操作流程。
|
Docker 容器
docker安装minio
以上就是在Docker中安装MinIO的步骤。
580 2
|
机器学习/深度学习 算法 算法框架/工具
深度学习在图像识别中的应用及代码实现
【8月更文挑战第3天】深度学习技术在图像识别领域取得了显著的成果,通过构建深度神经网络模型,实现了对复杂图像数据的高效处理和准确识别。本文将介绍深度学习在图像识别中的原理、关键技术及应用实例,并通过代码示例展示如何利用深度学习框架进行图像识别任务的实现。
|
网络协议 安全 网络安全
OSPF DR BDR选举:网络稳定性的关键角色
【4月更文挑战第22天】
695 0