索引: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 }
擴展類 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 }
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 週二