【Stack Overflow -- 原创加工、原创整理、生产实战】-- 深度复制

索引:

目录索引

一、说明

  1.本程序的核心代码不是我原创的,是我在Stack Overflow上搜集后加工出来的,原作者已忘记了~

  2.这段程序是我在上海携程(2014年左右)上班时整理并在生产环境应用的,先后经历了三家公司项目中使用,稳定可靠,放心使用

  3.扩展方法部分可根据自己实际需要修改,流可以搞个static,pool,也可以每次 new,根据项目性能需求自己定制就行了

二、代码

  代码如下:

  核心类  NonSerialiazableTypeSurrogateSelector :  

  1     /// <summary>
  2     /// 深度复制 / Surrogate
  3     /// </summary>
  4     public class NonSerialiazableTypeSurrogateSelector : ISerializationSurrogate, ISurrogateSelector
  5     {
  6         /// <summary>
  7         /// _nextSelector
  8         /// </summary>
  9         ISurrogateSelector _nextSelector;
 10 
 11         #region ISerializationSurrogate / 实现
 12         /// <summary>
 13         /// GetObjectData
 14         /// </summary>
 15         public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
 16         {
 17             FieldInfo[] fieldInfos = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
 18             foreach (var fi in fieldInfos)
 19             {
 20                 if (IsKnownType(fi.FieldType))
 21                 {
 22                     info.AddValue(fi.Name, fi.GetValue(obj));
 23                 }
 24                 else if (fi.FieldType.IsClass)
 25                 {
 26                     info.AddValue(fi.Name, fi.GetValue(obj));
 27                 }
 28             }
 29         }
 30 
 31         /// <summary>
 32         /// SetObjectData
 33         /// </summary>
 34         public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
 35         {
 36             FieldInfo[] fieldInfos = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
 37             foreach (var fi in fieldInfos)
 38             {
 39                 if (IsKnownType(fi.FieldType))
 40                 {
 41                     if (IsNullableType(fi.FieldType))
 42                     {
 43                         Type argumentValueForTheNullableType = GetFirstArgumentOfGenericType(fi.FieldType);
 44                         fi.SetValue(obj, info.GetValue(fi.Name, argumentValueForTheNullableType));
 45                     }
 46                     else
 47                     {
 48                         fi.SetValue(obj, info.GetValue(fi.Name, fi.FieldType));
 49                     }
 50                 }
 51                 else if (fi.FieldType.IsClass)
 52                 {
 53                     fi.SetValue(obj, info.GetValue(fi.Name, fi.FieldType));
 54                 }
 55             }
 56             return obj;
 57         }
 58         #endregion
 59 
 60         #region ISurrogateSelector / 实现
 61         /// <summary>
 62         /// ChainSelector
 63         /// </summary>
 64         public void ChainSelector(ISurrogateSelector selector)
 65         {
 66             this._nextSelector = selector;
 67         }
 68 
 69         /// <summary>
 70         /// GetNextSelector
 71         /// </summary>
 72         public ISurrogateSelector GetNextSelector()
 73         {
 74             return _nextSelector;
 75         }
 76 
 77         /// <summary>
 78         /// GetSurrogate
 79         /// </summary>
 80         public ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector)
 81         {
 82             if (IsKnownType(type))
 83             {
 84                 selector = null;
 85                 return null;
 86             }
 87             else if (type.IsClass || type.IsValueType)
 88             {
 89                 selector = this;
 90                 return this;
 91             }
 92             else
 93             {
 94                 selector = null;
 95                 return null;
 96             }
 97         }
 98         #endregion
 99 
100         #region 私有方法
101         /// <summary>
102         /// 是否为已知类型 / String,Primitive,Serializable
103         /// </summary>
104         private bool IsKnownType(Type type)
105         {
106             return type == typeof(string) || type.IsPrimitive || type.IsSerializable;
107         }
108 
109         /// <summary>
110         /// 是否为可空类型
111         /// </summary>
112         private bool IsNullableType(Type type)
113         {
114             if (type.IsGenericType)
115             {
116                 return type.GetGenericTypeDefinition() == typeof(Nullable<>);
117             }
118             return false;
119         }
120 
121         /// <summary>
122         /// GetFirstArgumentOfGenericType
123         /// </summary>
124         private Type GetFirstArgumentOfGenericType(Type type)
125         {
126             return type.GetGenericArguments()[0];
127         }
128         #endregion
129     }
NonSerialiazableTypeSurrogateSelector.cs

  扩展类 ObjectMethodExtensions :

 1     public static class ObjectMethodExtensions
 2     {
 3         /// <summary>
 4         /// 深度复制 (值类型/包装类型/引用类型/序列化/非序列化/标识序列化/非标识序列化,皆可深度复制)
 5         /// </summary>
 6         public static T DeepClone<T>(this T obj)
 7         {
 8             var result = default(T);
 9             try
10             {
11                 IFormatter formatter = new BinaryFormatter();
12                 formatter.SurrogateSelector = new SurrogateSelector();
13                 formatter.SurrogateSelector.ChainSelector(new NonSerialiazableTypeSurrogateSelector());
14                 var ms = new MemoryStream();
15                 formatter.Serialize(ms, obj);
16                 ms.Position = 0;
17                 result = (T)formatter.Deserialize(ms);
18             }
19             catch (Exception ex)
20             {
21                 throw new Exception("方法:DeepClone<T>(this T obj)出错.", ex);
22             }
23             return result;
24         }
25     }
ObjectMethodExtensions.cs  

三、.Net 内置类 与 代码说明

  BinaryFormatter:

  以二进制格式序列化和反序列化对象或连接对象的整个图形。

  https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx 

  SurrogateSelector:

  可帮助您选择要委派序列化或反序列化到的进程的序列化代理项中的格式化程序。

  https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.surrogateselector(v=vs.110).aspx

  MemoryStream :

  创建一个流,其后备存储为内存。

  https://msdn.microsoft.com/zh-cn/library/system.io.memorystream.aspx

  ISerializationSurrogate :

  Implements a serialization surrogate selector that allows one object to perform serialization and deserialization of another.

  (自己翻译~)

  https://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializationsurrogate(v=vs.110).aspx

  ISurrogateSelector:

  指示序列化代理项选择器类。

  https://msdn.microsoft.com/zh-cn/library/system.runtime.serialization.isurrogateselector

四、使用方式

  直接在要深度复制的实例对象后.DeepClone()即可,如:

  当然如果你不嫌麻烦,也可以指定类型,如:

  使用,是就是这样使用就行了,其中 扩展方法部分 可根据使用的频次做性能优化~

                                         蒙

                                    2017-07-11 19:07  周二

原文地址:https://www.cnblogs.com/Meng-NET/p/7152159.html