导出操作中,我们常常不需要显示所有属性,比如Person类加入Guid属性:
public class Person { public Int32 ID { get; set; } public Guid Guid { get; set; } public String Name { get; set; } public DateTime Birth { get; set; } public Double Salary { get; set; } }
现在要求传入字符串数组headers,有什么显示什么,Type. GetProperty()方法可以取单个属性,我们加入Export的重载方法如下:
static void Export<T>(IList<T> records, IList<String> headers) { if (records == null) throw new ArgumentNullException("records"); if (headers == null || headers.Count == 0) throw new ArgumentNullException("headers"); //像headers不可包含null元素、至少包含一个元素、元素不可重复等检查视需求而定, 下文不重重复 PropertyInfo[] props = new PropertyInfo[headers.Count]; for (Int32 i = 0; i < headers.Count; i++) { props[i] = typeof(T).GetProperty(headers[i]); //注意可能产生为null的元素 } for (Int32 i = 0; i < headers.Count; i++) { Console.Write(headers[i]); Console.Write("\t"); } Console.WriteLine(); foreach (var record in records) { for (Int32 i = 0; i < props.Length; i++) { if (props[i] != null) //注意null检查 { Object value = props[i].GetValue(record, null); Console.Write(value); Console.Write("\t"); } } Console.WriteLine(); } }
第一个方法重构如下:
static void Export<T>(IList<T> records) { if (records == null) throw new ArgumentNullException("records"); String[] headers = typeof(T).GetProperties().Select(p => p.Name).ToArray(); Export<T>(records, headers); }
现在的导出操作,我们只打印提供的属性数组,同时请注意:小写的“birth”匹配不到任何属性。
Export<Person>(persons, new[] { "Name", "birth", "Salary" });
继续加入业务场景,以上代码使用了属性名,我们可以更友好,比如将“Name”打印为“名称”,“Salary”打印成“薪水”——题外话,好像没啥场景需要打印薪水,Whatever. 加一个辅助的Header类如下,并添加Export重载:
public class Header { public String Name { get; private set; } public String PrintName { get; private set; } public Header(String name) : this(name, name) { } public Header(String name, String printName) { Name = name; PrintName = printName; } }
新的Export方法第2个重载与第3个重载分别为:
static void Export<T>(IList<T> records, IList<String> headers) { if (records == null) throw new ArgumentNullException("records"); if (headers == null || headers.Count == 0) throw new ArgumentNullException("headers"); Header[] newHeaders = typeof(T).GetProperties().Select(p => new Header(p.Name)).ToArray(); Export<T>(records, newHeaders); } static void Export<T>(IList<T> records, IList<Header> headers) { if (records == null) throw new ArgumentNullException("records"); if (headers == null || headers.Count == 0) throw new ArgumentNullException("headers"); PropertyInfo[] props = new PropertyInfo[headers.Count]; for (Int32 i = 0; i < headers.Count; i++) { props[i] = typeof(T).GetProperty(headers[i].Name); //注意属性数组仍然可以有元素为null } for (Int32 i = 0; i < headers.Count; i++) { Console.Write(headers[i].PrintName); Console.Write("\t"); } Console.WriteLine(); foreach (var record in records) { for (Int32 i = 0; i < props.Length; i++) { if (props[i] != null) //注意null检查 { Object value = props[i].GetValue(record, null); Console.Write(value); Console.Write("\t"); } } Console.WriteLine(); } }
调用逻辑与输出如下:
List<Header> headers = new List<Header>(); headers.Add(new Header("ID")); headers.Add(new Header("Name", "名称")); headers.Add(new Header("Salary", "薪水")); Export<Person>(persons, headers);
ID 名称 薪水 1 Rattz 20.2 2 Mike 20.2