技术开发 频道

ToString(string format) 扩展

  【IT168  技术文档】在.Net中,System.Object.ToString()是用得最多的方法之一,ToString()方法在Object类中被定义为virtual,Object类给了它一个默认实现:

public virtual string ToString()

   {

  
return this.GetType().ToString();

  }

  .Net中原生的class或struct,如int,DateTime等都对它进行重写(override),以让它返回更有价值的值,而不是类型的名称。合理重写的ToString()方法中编程、调试中给我们很大方便。但终究一个类只有一个ToString()方法,不能满足我们多样化的需求,很多类都对ToString()进行了重载。如下:

string dateString = DateTime.Now.ToString("yyyy"); //2009

string intString = 10.ToString("d4"); //0010

  int、DateTime都实现了ToString(string format)方法,极大方便了我们的使用。

  对于我们自己定义的类型,我们也应该提供一个合理的ToString()重写,如果能够提供再提供一个ToString(string format),就会令我们后期的工作更加简单。试看以下类型:

public class People

   {

  
private List friends = new List();

  

  
public int Id { get; set; }

  
public string Name { get; set; }

  
public DateTime Brithday { get; set; }

  
public People Son { get; set; }

  
public People[] Friends { get { return friends.ToArray(); } }

  

  
public void AddFriend(People newFriend)

   {

  
if (friends.Contains(newFriend)) throw new ArgumentNullException("newFriend", "该朋友已添加");

  
else friends.Add(newFriend);

   }

  
public override string ToString()

   {

  
return string.Format("Id: {0}, Name: {1}", Id, Name);

   }

   ……

   }

  一个简单的类,我们给出一个ToString()重写,返回包含Id和Name两个关键属性的字符串。现在我们需要一个ToString(string format)重写,以满足以下应用:

People p = new People { Id = 1, Name = "鹤冲天", Brithday = new DateTime(1990, 9, 9) };
string s0 = p.ToString("Name 生日是 Brithday"); //理想输出:鹤冲天 生日是 1990-9-9
string s1 = p.ToString("编号为:Id,姓名:Name"); //理想输出:编号为:1,姓名:鹤冲天

 

  想想怎么实现吧,记住format是可变的,不定使用了什么属性,也不定进行了怎样的组合...

  也许一个类好办,要是我们定义很多类,几十、几百个怎么办?一一实现ToString(string format)会把人累死的。好在我们有扩展方法,我们对object作一扩展ToString(string format),.Net中object是所有的基类,对它扩展后所有的类都会自动拥有了。当然已有ToString(string format)实现的不会,因为原生方法的优先级高,不会被扩展方法覆盖掉。

  来看如何实现吧:

public static string ToString1(this object obj, string format)

   {

   Type type
= obj.GetType();

   PropertyInfo[] properties
= type.GetProperties(

   BindingFlags.GetProperty
| BindingFlags.Public | BindingFlags.Instance);

  

  
string[] names = properties.Select(p => p.Name).ToArray();

  
string pattern = string.Join("|", names);

  

   MatchEvaluator evaluator
= match =>

   {

   PropertyInfo property
= properties.First(p => p.Name == match.Value);

  
object propertyValue = property.GetValue(obj, null);

  
if (propertyValue != null) return propertyValue.ToString();

  
else return "";

   };

  
return Regex.Replace(format, pattern, evaluator);

   }

  3~5行通过反射获取了公有的、实例的Get属性(如果需要静态的或私有的,修改第5行中即可),7~8行动态生成一个正则表达式来匹配format,10~16行是匹配成功后的处理。这里用到反射和正则表达式,如果不熟悉不要紧,先调试运行吧,测试一下前面刚提到的应用:

        

0
相关文章