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

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

編輯:關於C語言

在.Net中,System.Object.ToString()是用得最多的方法之一,ToString()方法在Object類中被定義為virtual,Object類給了它一個默認實現:

1 public virtual string ToString()
2 {
3  return this.GetType().ToString();
4 }

.Net中原生的class或struct,如int,DateTime等都對它進行重寫(override),以讓它返回更有價值的值,而不是類型的名稱。合理重寫的ToString()方法中編程、調試中給我們很大方便。但終究一個類只有一個ToString()方法,不能滿足我們多樣化的需求,很多類都對ToString()進行了重載。如下:

1 string dateString = DateTime.Now.ToString("yyyy");  //2009
2 string intString = 10.ToString("d4");  //0010

int、DateTime都實現了ToString(string format)方法,極大方便了我們的使用。

對於我們自己定義的類型,我們也應該提供一個合理的ToString()重寫,如果能夠提供再提供一個ToString(string format),就會令我們後期的工作更加簡單。試看以下類型: 

1 public class People
2 {
3  private List<People> frIEnds = new List<People>();
4 
5  public int Id { get; set; }
6  public string Name { get; set; }
7  public DateTime Brithday { get; set; }
8  public People Son { get; set; }
9  public People[] Friends { get { return frIEnds.ToArray(); } }
10
11  public void AddFriend(People newFrIEnd)
12  {
13   if (friends.Contains(newFriend)) throw new ArgumentNullException("newFrIEnd", "該朋友已添加");
14   else friends.Add(newFrIEnd);
15  }
16  public override string ToString()
17  {
18   return string.Format("Id: {0}, Name: {1}", Id, Name);
19  }
20 
21 }

一個簡單的類,我們給出一個ToString()重寫,返回包含Id和Name兩個關鍵屬性的字符串。現在我們需要一個ToString(string format)重寫,以滿足以下應用:

1 People p = new People { Id = 1, Name = "鶴沖天", Brithday = new DateTime(1990, 9, 9) };
2 string s0 = p.ToString("Name 生日是 Brithday"); //理想輸出:鶴沖天 生日是 1990-9-9
3 string s1 = p.ToString("編號為:Id,姓名:Name"); //理想輸出:編號為:1,姓名:鶴沖天

想想怎麼實現吧,記住format是可變的,不定使用了什麼屬性,也不定進行了怎樣的組合...

也許一個類好辦,要是我們定義很多類,幾十、幾百個怎麼辦?一一實現ToString(string format)會把人累死的。好在我們有擴展方法,我們對object作一擴展ToString(string format),.Net中object是所有的基類,對它擴展後所有的類都會自動擁有了。當然已有ToString(string format)實現的不會,因為原生方法的優先級高,不會被擴展方法覆蓋掉。

來看如何實現吧(我們會一步一步改進,為區分各個版本,分別擴展為ToString1、ToString2...分別對應版本一、版本二...):

1 public static string ToString1(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   string[] names = propertIEs.Select(p => p.Name).ToArray();
8   string pattern = string.Join("|", names);
9
10   MatchEvaluator evaluator = match =>
11   {
12    PropertyInfo property = propertIEs.First(p => p.Name == match.Value);
13    object propertyValue = property.GetValue(obj, null);
14    if (propertyValue != null) return propertyValue.ToString();
15    else return "";
16   };
17   return Regex.Replace(format, pattern, evaluator);
18 }

3~5行通過反射獲取了公有的、實例的Get屬性(如果需要靜態的或私有的,修改第5行中即可),7~8行動態生成一個正則表達式來匹配format,10~16行是匹配成功後的處理。這裡用到反射和正則表達式,如果不熟悉不要緊,先調試運行吧,測試一下前面剛提到的應用:

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