我們在日常接觸到的一些軟件界面,往往喜歡深入分析其實現機理,通過學習、分析,可以提高我們對軟件架構的分析能力,從而實現更加彈性、可重用的模塊。在無意間,看到一個短信模塊的設計,模板里面可以包含了很多變量,從而引發我對其深入分析的興趣,本文主要介紹我對這些實現的一些理解,介紹一個包含動態變量的短信模板的設計分析。
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", 公司 = "廣州愛奇迪軟件科技有限公司" };
測試案例,我們可以得到的消息,如下所示。
我們從上面截圖可以看到,真正的消息已經正確得到,這些是替換具體的模板內容形成的,如果我們在整體的模板設計里面,采用這個思路,就可以實現動態的模板消息發送,從而實現了比較彈性化的設計處理。
本文只是對模板變量這種場景進行了分析,我們在實際項目中,可以更加完善,實現更加強大的模板消息處理,以及利用微信模板消息進行一起發送,實現短信、微信,甚至郵件的同步通知,給客戶更好的體驗。
以上是微信的模板消息介紹,我們也可以結合動態變量,把對應模板消息替換為我們要發送的消息,從而也實現了微信消息的動態發送。