【Stack Overflow -- 原創加工、原創整理、生產實戰】-- 深度複製

索引:html

目錄索引性能優化

1、說明ide

  1.本程序的核心代碼不是我原創的,是我在Stack Overflow上搜集後加工出來的,原做者已忘記了~性能

  2.這段程序是我在上海攜程(2014年左右)上班時整理並在生產環境應用的,前後經歷了三家公司項目中使用,穩定可靠,放心使用優化

  3.擴展方法部分可根據本身實際須要修改,流能夠搞個static,pool,也能夠每次 new,根據項目性能需求本身定製就好了this

2、代碼spa

  代碼以下:翻譯

  核心類  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 :code

 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  

3、.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

4、使用方式

  直接在要深度複製的實例對象後.DeepClone()便可,如:

  固然若是你不嫌麻煩,也能夠指定類型,如:

  使用,是就是這樣使用就好了,其中 擴展方法部分 可根據使用的頻次作性能優化~

 

 

                                         蒙

                                    2017-07-11 19:07  週二

相關文章
相關標籤/搜索