用C#写WPF程序, 实现功能的过程中碰到一个需求: 动态设置对象的属性,属性名称是未知的,在运行时才能确定。
本来这种需求可以用 Dictionary<string, object> 实现, 但是由于对某个库的依赖,必须使用匿名类型对象
var obj = new{ Title = "标题", Content = "内容", Date = DateTime.Now, Num = };
而这种对象的属性名称必须硬编码写死,无法在运行时设置,因此这种方法无法满足我的需求。
通过在网上查阅相关资料,发现一种 System.Dynamic.ExpandoObject 类型的对象,在在非常规的使用模式下可以实现我的需求。
dynamic obj = new System.Dynamic.ExpandoObject(); obj.Title = "标题"; obj.Content = "内容"; obj.Date = DateTime.Now; obj.Num = ;
这是 ExpandoObject 的最普通的使用方法, 还不足以满足需求。而且,ExpandoObject 也不能使用索引器的方式访问对象属性。 然而,ExpandoObject 实现了 IDictionary<string, object> 接口,也就是说只要 ExpandoObject 类型的对象向上转型为 IDictionary<string, object> 类型对象,就可以使用索引器的方式访问对象的属性了。
dynamic obj = new System.Dynamic.ExpandoObject(); var dic = obj as IDictionary<string, object>; dic[ "Title" ] = "标题"; dic[ "Content" ] = "内容"; dic[ "Date " ] = DateTime.Now; dic[ ;
因为obj变量和dic变量引用的是同一个对象, 所以通过两个变量中任意一个变量修改对象的值, 都能反映到彼此身上。而dic对象拥有通过索引器修改属性的能力,这也就意味着obj变量间接的具备了这种能力。于是我碰到的问题就得到了解决:将 DataTable类型对象转换成匿名类型对象列表
public static List<Object> Convert(DataTable data) { var objectList = new List<Object>(); foreach( DataRow row in data.Rows ) { dynamic dataItem = new System.Dynamic.ExpandoObject(); var dataItemDic = dataItem as IDictionary<string, object>; foreach( DataColumn col in data.Columns ) { var name = col.ColumnName; var val = row[name].ToString(); dataItemDic[ name ] = val; } objectList.Add( dataItem ); } return objectList; }