利用dynamic解决匿名对象不能赋值的问题

关于匿名对象

匿名对象是.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是等价的,这为我们开发带来了很大的灵活性,但这样做的性能开销目前还没有深入研究,如果有哪位朋友测试过,也请告知,谢谢。

posted @ 2012-02-17 19:25  L.Qiu  阅读(4000)  评论(4编辑  收藏  举报