程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> c#擴展方法奇思妙用高級篇五:ToString(string format) 擴展(2)

c#擴展方法奇思妙用高級篇五:ToString(string format) 擴展(2)

編輯:關於C語言

第一個和我們理想的有點差距,就是日期上,我們應該給日期加上"yyyy-MM-dd"的格式,這個我們稍後改進,我們現在有一個更大的問題:

如果我們想輸出:“People: Id 1, Name 鶴沖天”,format怎麼寫呢?寫成format="People: Id Id, Name Name",這樣沒法處理了,format中兩個Id、兩個Name,哪個是常量,哪個是變量啊?解決這個問題,很多種方法,如使用轉義字符,可是屬性長了不好寫,如format="\B\r\i\t\h\d\a\y Brithday"。我權衡了一下,最後決定采用類似Sql中對字段名的處理方法,在這裡就是給變量加上中括號,如下:

1 People p2 = new People { Id = 1, Name = "鶴沖天", Brithday = new DateTime(1990, 9, 9) };
2 string s2 = p1.ToString2("People:Id [Id], Name [Name], Brithday [Brithday]");

版本二的實現代碼如下:

1 public static string ToString2(this object obj, string format)
2 {
3  Type type = obj.GetType();
4  PropertyInfo[] properties = type.GetPropertIEs(
5  BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);
6 
7  MatchEvaluator evaluator = match =>
8  {
9   string propertyName = match.Groups["Name"].Value;
10  PropertyInfo property = propertIEs.FirstOrDefault(p => p.Name == propertyName);
11  if (property != null)
12   {
13    object propertyValue = property.GetValue(obj, null);
14    if (propertyValue != null) return propertyValue.ToString();
15    else return "";
16   }
17   else return match.Value;
18  };
19  return Regex.Replace(format, @"\[(?<Name>[^\]]+)\]", evaluator, RegexOptions.Compiled);
20 }

調試執行一下:

與版本一類似,不過這裡沒有動態構建正則表達式,因為有了中括號,很容易區分常量和變量,所以我們通過“屬性名”來找“屬性”(對應代碼中第10行)。如果某個屬性找不到,我們會將這“[Name]”原樣返回(對就第17行)。另一種做法是拋出異常,我不建議拋異常,在ToString(string format)是不合乎“常理”的。

版本二相對版本一效率有很大提高,主要是因為版本二只使用一個簡單的正則表達式:@"\[(?<Name>[^\]]+)\]"。而版本一中的如果被擴展類的屬性特別多,動態生成的正則表達式會很長,執行起來也會相對慢。

我們現在來解決兩個版本中都存在的時間日期格式問題,把時間日期格式"yyyy-MM-dd"也放入中括號中,測試代碼如下:

1 People p3 = new People { Id = 1, Name = "鶴沖天", Brithday = new DateTime(1990, 9, 9) };
2 string s3 = p3.ToString3("People:Id [Id: d4], Name [Name], Brithday [Brithday: yyyy-MM-dd]");

版本三實現代碼:

1 public static string ToString3(this object obj, string format)
2 {
3  Type type = obj.GetType();
4  PropertyInfo[] properties = type.GetPropertIEs(
5  BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);
6 
7  MatchEvaluator evaluator = match =>
8  {
9   string propertyName = match.Groups["Name"].Value;
10   string propertyFormat = match.Groups["Format"].Value;
11
12   PropertyInfo propertyInfo = propertIEs.FirstOrDefault(p => p.Name == propertyName);
13   if (propertyInfo != null)
14   {
15    object propertyValue = propertyInfo.GetValue(obj, null);
16    if (string.IsNullOrEmpty(propertyFormat) == false)
17     return string.Format("{0:" + propertyFormat + "}", propertyValue);
18    else return propertyValue.ToString();
19   }
20   else return match.Value;
21  };
22  string pattern = @"\[(?<Name>[^\[\]:]+)(\s*:\s*(?<Format>[^\[\]:]+))?\]";
23  return Regex.Replace(format, pattern, evaluator, RegexOptions.Compiled);
24 }

測試一下,可OK了:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved