[转载]利用dynamic解决匿名对象不能赋值的问题 – L.Qiu – 博客园.
匿名对象是.Net Framework 3.0提供的新类型,例如:
var obj = { Name = "aa", Value = 1 };
就是一个匿名类,搭配Linq,可以很灵活的在代码中组合数据,例如:
var r = from p in DbContext.Actions
select new {
A = p.Name,
B = p.Text
};
特殊需求:给匿名对象属性赋值
但有时候会有一些特殊的要求,需要给获取的匿名对象的某些属性进行赋值,例如如下的代码:
//根据上例使用LINQ获取的结果集 foreach(var item in r) { item.A = "new name"; }
以上这段代码在运行时,会抛出异常“该对象的属性是只读的”。说明匿名类在内部实现上,只能在初始化的时候赋值,如果想再次改变,对不起,这样是不可以的。
解决方案
但有的时候确实是有这样的需求,那有什么方法可以解决呢? 经过研究,发现可以采用如下的方案解决,本人已经验证通过。
答案就是使用C# 4.0里面新提供的动态类型:dynamic
直接上代码,想必大家一看就明白了:
//声明dynamic泛型集合 List<dynamic> newpayList = new List<dynamic>(); payList.ForEach(t => { //new 一个ExpandoObject对象 dynamic d = new System.Dynamic.ExpandoObject(); d.IntervalDay = 0; d.Percent = Math.Round(t.Amount / totalRevenue, 4); d.Amount = adjAmount * Math.Round(t.Amount / totalRevenue, 4); d.PayDate = t.EstPaymentDate; d.IsLast = false; newpayList.Add(d); }); var count = newpayList.Count(); for (int i = 0; i < count; i++) { var item = newpayList[i]; if (i != 0) { //改变动态类型的属性值 item.IntervalDay = (item.PayDate - newpayList[i - 1].PayDate).Days; } if( i == count - 1) item.IsLast = true; }
用动态类型取代匿名对象,但实际上,它们之间又有着紧密的联系,在某些时候,匿名对象和dynamic是等价的,这为我们开发带来了很大的灵活性,但这样做的性能开销目前还没有深入研究,如果有哪位朋友测试过,也请告知,谢谢。