从具有指定属性的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(fxn(item)); sb.Append(" "); } sb.Append(" \n"); } 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(GetName(fxn)); sb.Append(" "); } sb.Append(" \n"); foreach (var item in list) { sb.Append("\n"); foreach (var fxn in fxns) { sb.Append(""); sb.Append(fxn.Compile()(item)); sb.Append(" "); } sb.Append(" \n"); } 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
- 使用C#和ASP.NET在E邮件附件中发送SQL报告
- 如何使用Identities列表从Entity Framework获取ObjectResult
- SqlCommand参数大小混乱
- WriteableBitmap上的异步操作
- 无法在Winforms中使用C#使用datagridview添加新行
- C#:当字段不为空时返回IEnumerable?
- 禁用所选Listview项目的蓝色边框
- 确定MSBuild CoreCompile是否将运行并调用自定义目标
- 标签数组
Interesting Posts
使用属性读取XML的最简单方法
将LDAP中的WhenChanged属性(Generalized-Time)转换为C#中的DateTime
C#/ ODP.NET:大型IN子句解决方法
从ASP.NET 1.1转换为ASP.Net 3.5后,单选按钮停止工作
使用mono / nunit-console / 4在Mac OS X控制台上运行测试
ClickOnce应用程序安装 – 安全警告
如何在C#中更改ComboBox的itemsSource
创建Xamarin.Forms跨平台应用程序时,“此项目需要加载Visual Studio更新”错误
entity framework“意外连接状态”例外
如何解释不同的实施需求?