扩展IList对象,实现深拷贝扩展方法
2012-02-29 16:50
288 查看
应用场景
对一个集合进行深拷贝复制,实现的方法有不少,现举一个常规实现方案:例如已有一个List<T> someListList<T> newList = new List<T>(); foreach(var item in someList) { T t = new T(); //此处的属性如果是引用类型,还需要考虑该类型的深拷贝实现 t.P1 = item.P1; t.P2 = item.P2;
... newList.Add(t); }
如果类似的需求不止一个,那我们就要反复书写类似的代码,这显然不符合代码重用的原则。
思路
首先想到的应该是扩展方法,并且是基于泛型的扩展方法,这个简单,上代码:public static IList<T> Clone<T>(this IList<T> source) { IList<T> newList = new List<T>(source.Count); foreach (var item in source) { newList.Add(..); } return newList; }
这个add方法里还是要new一个T对象,并且挨个给属性赋值,那岂不是也很麻烦,这时候肯定有同学想到了反射,对,使用反射可以解决这个问题,但我认为还不是很理想。
第二次思考。。。对了,微软不是已经为我们提供了一个接口叫ICloneable的么?我们应该为T加上约束,修改代码如下:
public static IList<T> Clone<T>(this IList<T> source) where T : ICloneable { IList<T> newList = new List<T>(source.Count); foreach (var item in source) { newList.Add((T)((ICloneable)item.Clone())); } return newList; }
现在看上去还不错了,基本思路已经成型,在调用的时候可以这样使用: newList = someList.Clone();
当然,别忘了给你的T加上ICloneable接口,并实现Clone方法,实现Clone的方法有很多,个人建议如下:
public object Clone() { MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, this); stream.Position = 0; var obj = formatter.Deserialize(stream) as Class; return obj; }
使用序列化的方式进行对象的复制,这样做的前提是你的Class需要被标记为Serializable。
使用EF时碰到的实际案例
例如一个Entity有很多关联的实体(主子表),现在需要复制原始记录作为一份全新的记录,包括所有的子表,如果采用常规方法,做起来是会很繁琐的,需要挨个遍历子表集合,并new一个全新的实体对象,再挨个执行AddObject,如果采用上面的方案,代码如下://子表集合 var resList = this.ResourcePlanService.GetList(t => t.QuoteID == quoteId).ToList(); ForeachCopy(resList, this.ResourcePlanService); private void ForeachCopy<TModel, TService>(IList<TModel> list, TService service) where TService : IService<TModel> where TModel : ICloneable { list.Clone().ForEach( t => service.Add(t) ); }
这样代码就精简了很多,对原来的改动也相对较小,只需要把TModel的基类EntityObjectBase实现ICloneable接口,并实现Clone方法即可,需要注意的是,如果EF采用DB First方式,则需要在Clone方法里面把EntityKey设置为null,否则,在调用AddObject的时候,ObjectManagement会抛出异常。
总结
优点:代码简单、复用度高缺点:需要修改类对象以继承ICloneable接口,如果没有基类的话,也是一个很麻烦的问题,并且类对象需要被标记为Serializable
相关文章推荐
- 扩展IList对象,实现深拷贝扩展方法
- 扩展IList对象,实现深拷贝扩展方法
- 原生js实现复制对象、扩展对象 类似jquery中的extend()方法
- 解决用序列化方式实现对象拷贝时出的异常解决方法
- 浅谈javascript对象、如何实现继承、jQuery方法的扩展(jquery插件)
- 使用遍历的方法实现对对象的深拷贝
- 五星-原型模式常使用于以下场景--而JAVA中的任何类只要实现了Cloneable标识接口,就可以使用clone方法来进行对象的拷贝
- 用LinQ扩展方法,泛型扩展方法,实现自定义验证字符是否空、对象是否为null,及泛型约束使用,Action的使用
- 实现一个对象验证库系列 -- 3) Fluent以及扩展方法实现 (请大神批评)
- 原生js实现复制对象、扩展对象 类似jquery中的extend()方法
- .Net3.5扩展方法实现对象JSON序列化
- [导入].Net3.5扩展方法实现对象JSON序列化
- 2种方法实现java对象的深拷贝
- js实现复制对象、扩展对象 方法
- 使用扩展方法和静态门面类实现伪领域对象
- 原生js实现复制对象、扩展对象 类似jquery中的extend()方法
- 地磅称量系统之(53)在封装对象的类库中实现包括IDataErrorInfo接口提供的所有方法和并且扩展对异常具有添加和删除功能的基本业务对象基类
- 原生js实现复制对象、扩展对象 类似jquery中的extend()方法
- 学习effective java-12对所有对象共同的方法之考虑实现Comparable
- iOS category中的所谓属性 和 从xib初始化对象的方法 以及类扩展