⼀个包含动态变量的短信模板设计分析
我们在⽇常接触到的⼀些软件界⾯,往往喜欢深⼊分析其实现机理,通过学习、分析,可以提⾼我们对软件架构的分析能⼒,从⽽实现更加弹性、可重⽤的模块。在⽆意间,看到⼀个短信模块的设计,模板⾥⾯可以包含了很多变量,从⽽引发我对其深⼊分析的兴趣,本⽂主要介绍我对这些实现的⼀些理解,介绍⼀个包含动态变量的短信模板的设计分析。
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", 公司 = "⼴州爱奇迪软件科技有限公司" };
writeline输出数值变量
测试案例,我们可以得到的消息,如下所⽰。
我们从上⾯截图可以看到,真正的消息已经正确得到,这些是替换具体的模板内容形成的,如果我们在整体的模板设计⾥⾯,采⽤这个思路,就可以实现动态的模板消息发送,从⽽实现了⽐较弹性化的设计处理。
本⽂只是对模板变量这种场景进⾏了分析,我们在实际项⽬中,可以更加完善,实现更加强⼤的模板消息处理,以及利⽤模板消息进⾏⼀起发送,实现短信、,甚⾄邮件的同步通知,给客户更好的体验。
以上是的模板消息介绍,我们也可以结合动态变量,把对应模板消息替换为我们要发送的消息,从⽽也实现了消息的动态发送。