从具有指定属性的generics类列表生成HTML表

我想从几个指定的参数生成一个HTML表。 具体来说,我想传递给我的方法的两个参数是:IEnumerable列表,以及T的一些属性子集。例如,假设我有一个这个类的List:

class Person { string FirstName string MiddleName string LastName } 

假设该列表中有5个人。 我想通过这样的方式获得该类(或任何其他任意类)的HTML表:

 List people; ...add people to list string HTML = GetMyTable(people, "FirstName", "LastName"); 

我确信有一种更好的方法可以指定我想要从表中生成哪些属性(或者我希望从表中排除哪些属性,这样会更好,因为我通常需要大多数或所有类的属性),但是我我不确定如何(我从未使用过reflection,但我猜这是怎么回事)。 此外,该方法应接受任何类型的类的列表。

有关如何实现这一目标的任何聪明的想法?

也许是这样的?

 var html = GetMyTable(people, x => x.LastName, x => x.FirstName); public static string GetMyTable(IEnumerable list,params Func[] fxns) { StringBuilder sb = new StringBuilder(); sb.Append("\n"); foreach (var item in list) { sb.Append("\n"); foreach(var fxn in fxns) { sb.Append(""); } sb.Append("\n"); } sb.Append("
"); sb.Append(fxn(item)); sb.Append("
"); return sb.ToString(); }

– 版本2.0–

 public static string GetMyTable(IEnumerable list, params Expression>[] fxns) { StringBuilder sb = new StringBuilder(); sb.Append("\n"); sb.Append("\n"); foreach (var fxn in fxns) { sb.Append(""); } sb.Append("\n"); foreach (var item in list) { sb.Append("\n"); foreach (var fxn in fxns) { sb.Append(""); } sb.Append("\n"); } sb.Append("
"); sb.Append(GetName(fxn)); sb.Append("
"); sb.Append(fxn.Compile()(item)); sb.Append("
"); return sb.ToString(); } static string GetName
(Expression> expr) { var member = expr.Body as MemberExpression; if (member != null) return GetName2(member); var unary = expr.Body as UnaryExpression; if (unary != null) return GetName2((MemberExpression)unary.Operand); return "?+?"; } static string GetName2(MemberExpression member) { var fieldInfo = member.Member as FieldInfo; if (fieldInfo != null) { var d = fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute; if (d != null) return d.Description; return fieldInfo.Name; } var propertInfo = member.Member as PropertyInfo; if (propertInfo != null) { var d = propertInfo.GetCustomAttribute(typeof(DescriptionAttribute)) as DescriptionAttribute; if (d != null) return d.Description; return propertInfo.Name; } return "?-?"; }

PS:重复调用fxn.Compile()可能会在紧密循环中成为性能杀手。 将它缓存在字典中会更好。

这就是我所做的,它似乎工作正常,而不是一个巨大的性能打击。

  public static string ToHtmlTable(this List listOfClassObjects) { var ret = string.Empty; return listOfClassObjects == null || !listOfClassObjects.Any() ? ret : "" + listOfClassObjects.First().GetType().GetProperties().Select(p => p.Name).ToList().ToColumnHeaders() + listOfClassObjects.Aggregate(ret, (current, t) => current + t.ToHtmlTableRow()) + "
"; } public static string ToColumnHeaders
(this List listOfProperties) { var ret = string.Empty; return listOfProperties == null || !listOfProperties.Any() ? ret : "" + listOfProperties.Aggregate(ret, (current, propValue) => current + ("" + (Convert.ToString(propValue).Length <= 100 ? Convert.ToString(propValue) : Convert.ToString(propValue).Substring(0, 100)) + "..." + "")) + ""; } public static string ToHtmlTableRow(this T classObject) { var ret = string.Empty; return classObject == null ? ret : "" + classObject.GetType() .GetProperties() .Aggregate(ret, (current, prop) => current + ("" + (Convert.ToString(prop.GetValue(classObject, null)).Length <= 100 ? Convert.ToString(prop.GetValue(classObject, null)) : Convert.ToString(prop.GetValue(classObject, null)).Substring(0, 100) + "...") + "")) + ""; }

要使用它,只需传递ToHtmlTable()一个List示例:

List documents = GetMyListOfDocuments(); var table = documents.ToHtmlTable();

这是两种方法,一种使用reflection:

 public static string GetMyTable(IEnumerable list, params string[] columns) { var sb = new StringBuilder(); foreach (var item in list) { //todo this should actually make an HTML table, not just get the properties requested foreach (var column in columns) sb.Append(item.GetType().GetProperty(column).GetValue(item, null)); } return sb.ToString(); } //used like string HTML = GetMyTable(people, "FirstName", "LastName"); 

或者使用lambdas:

 public static string GetMyTable(IEnumerable list, params Func[] columns) { var sb = new StringBuilder(); foreach (var item in list) { //todo this should actually make an HTML table, not just get the properties requested foreach (var column in columns) sb.Append(column(item)); } return sb.ToString(); } //used like string HTML = GetMyTable(people, x => x.FirstName, x => x.LastName); 

使用lambdas,正在发生的是你将方法传递给GetMyTable方法来获取每个属性。 这有利于反击,如强类型和可能的性能。

祝你好运

扩展方法

  public static class EnumerableExtension { public static string ToHtmlTable(this IEnumerable list, List headerList, List customTableStyles, params Func[] columns) { if (customTableStyles == null) customTableStyles = new List(); var tableCss = string.Join(" ", customTableStyles?.Where(w => w.CustomTableStylePosition == CustomTableStylePosition.Table).Where(w => w.ClassNameList != null).SelectMany(s => s.ClassNameList)) ?? ""; var trCss = string.Join(" ", customTableStyles?.Where(w => w.CustomTableStylePosition == CustomTableStylePosition.Tr).Where(w => w.ClassNameList != null).SelectMany(s => s.ClassNameList)) ?? ""; var thCss = string.Join(" ", customTableStyles?.Where(w => w.CustomTableStylePosition == CustomTableStylePosition.Th).Where(w => w.ClassNameList != null).SelectMany(s => s.ClassNameList)) ?? ""; var tdCss = string.Join(" ", customTableStyles?.Where(w => w.CustomTableStylePosition == CustomTableStylePosition.Td).Where(w => w.ClassNameList != null).SelectMany(s => s.ClassNameList)) ?? ""; var tableInlineCss = string.Join(";", customTableStyles?.Where(w => w.CustomTableStylePosition == CustomTableStylePosition.Table).Where(w => w.InlineStyleValueList != null).SelectMany(s => s.InlineStyleValueList?.Select(x => String.Format("{0}:{1}", x.Key, x.Value)))) ?? ""; var trInlineCss = string.Join(";", customTableStyles?.Where(w => w.CustomTableStylePosition == CustomTableStylePosition.Tr).Where(w => w.InlineStyleValueList != null).SelectMany(s => s.InlineStyleValueList?.Select(x => String.Format("{0}:{1}", x.Key, x.Value)))) ?? ""; var thInlineCss = string.Join(";", customTableStyles?.Where(w => w.CustomTableStylePosition == CustomTableStylePosition.Th).Where(w => w.InlineStyleValueList != null).SelectMany(s => s.InlineStyleValueList?.Select(x => String.Format("{0}:{1}", x.Key, x.Value)))) ?? ""; var tdInlineCss = string.Join(";", customTableStyles?.Where(w => w.CustomTableStylePosition == CustomTableStylePosition.Td).Where(w => w.InlineStyleValueList != null).SelectMany(s => s.InlineStyleValueList?.Select(x => String.Format("{0}:{1}", x.Key, x.Value)))) ?? ""; var sb = new StringBuilder(); sb.Append($""); if (headerList != null) { sb.Append($""); foreach (var header in headerList) { sb.Append($"{header}"); } sb.Append(""); } foreach (var item in list) { sb.Append($""); foreach (var column in columns) sb.Append($"{column(item)}"); sb.Append(""); } sb.Append(""); return sb.ToString(); } public class CustomTableStyle { public CustomTableStylePosition CustomTableStylePosition { get; set; } public List ClassNameList { get; set; } public Dictionary InlineStyleValueList { get; set; } } public enum CustomTableStylePosition { Table, Tr, Th, Td } } 

运用

  private static void Main(string[] args) { var dataList = new List { new TestDataClass {Name = "A", Lastname = "B", Other = "ABO"}, new TestDataClass {Name = "C", Lastname = "D", Other = "CDO"}, new TestDataClass {Name = "E", Lastname = "F", Other = "EFO"}, new TestDataClass {Name = "G", Lastname = "H", Other = "GHO"} }; var headerList = new List { "Name", "Surname", "Merge" }; var customTableStyle = new List { new EnumerableExtension.CustomTableStyle{CustomTableStylePosition = EnumerableExtension.CustomTableStylePosition.Table, InlineStyleValueList = new Dictionary{{"font-family", "Comic Sans MS" },{"font-size","15px"}}}, new EnumerableExtension.CustomTableStyle{CustomTableStylePosition = EnumerableExtension.CustomTableStylePosition.Table, InlineStyleValueList = new Dictionary{{"background-color", "yellow" }}}, new EnumerableExtension.CustomTableStyle{CustomTableStylePosition = EnumerableExtension.CustomTableStylePosition.Tr, InlineStyleValueList =new Dictionary{{"color","Blue"},{"font-size","10px"}}}, new EnumerableExtension.CustomTableStyle{CustomTableStylePosition = EnumerableExtension.CustomTableStylePosition.Th,ClassNameList = new List{"normal","underline"}}, new EnumerableExtension.CustomTableStyle{CustomTableStylePosition = EnumerableExtension.CustomTableStylePosition.Th,InlineStyleValueList =new Dictionary{{ "background-color", "gray"}}}, new EnumerableExtension.CustomTableStyle{CustomTableStylePosition = EnumerableExtension.CustomTableStylePosition.Td, InlineStyleValueList =new Dictionary{{"color","Red"},{"font-size","15px"}}}, }; var htmlResult = dataList.ToHtmlTable(headerList, customTableStyle, x => x.Name, x => x.Lastname, x => $"{x.Name} {x.Lastname}"); } private class TestDataClass { public string Name { get; set; } public string Lastname { get; set; } public string Other { get; set; } } 

结果

 
Name Surname Merge
A B A B
C D C D
E F E F
G H G H