C#创建编译时动态属性对象和运行时动态属性对象(linq 动态列名)
void Main() { var list = new List<object>(); Enumerable.Range(1, 100).ToList().ForEach(item => { dynamic d = new System.Dynamic.ExpandoObject(); d.Name = "张三"; d.Gender = item % 3 == 0 ? "男" : "女"; (d as IDictionary<string, Object>).Add("Age", 30+item); list.Add(d); }); list.Dump(); }
对于需要临时使用一个类型,却用不想定义一个类。或者前端绑定的动态列名的情况,也非常方便。
结果如下:
经验证,这种数据集可以直接绑定到 WPF,但绑定到 asp.net GridView 和 winform 的 DataGridView 一个报错一个没反应,那就转成DataTable吧,一个扩展方法就搞定了
public static class DynamicExtension { public static DataTable ToDataTable(this IEnumerable<dynamic> items) { var data = items.ToArray(); if (data.Count() == 0) return null; var dt = new DataTable(); foreach (var key in ((IDictionary<string, object>)data[0]).Keys) { dt.Columns.Add(key); } foreach (var d in data) { dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray()); } return dt; } }
dynamic 类型竟然支持序列化与反序列化:
dynamic d = new ExpandoObject(); d.Name = "张三"; d.Gender = "男"; (d as IDictionary<string, Object>).Add("Age", 30); Console.WriteLine( Newtonsoft.Json.JsonConvert.SerializeObject(d)); dynamic x = Newtonsoft.Json.JsonConvert.DeserializeObject<ExpandoObject>( Newtonsoft.Json.JsonConvert.SerializeObject(d)); Console.WriteLine( x.Name); Console.WriteLine( x.Gender); Console.WriteLine( x.Age);
使用中发现ExpandoObject可以转为dynamic,但dynamic无法转换为ExpandoObject,切记不要相互转换,比如反序列化时选ExpandoObject,而不能选dynamic。
使用时还有一点需要注意,不要给dynamic无法识别的数据类型,如 null
桂棹兮兰桨,击空明兮溯流光。