• 【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  周二

  • 相关阅读:
    Discuz X3.2 分区 gid 完美伪静态方法 Apache/Nginx
    如何批量转换 WordPress 文章分类
    修改 WordPress 文件上传目录
    如何验证 jemalloc 优化 Nginx 是否生效
    .Net Core 1.1 + CentOs 7 环境配置
    DotNet Core中使用dapper
    爬虫 HttpHelper
    iTextSharp 不适用模板 代码拼接PDF
    .Net中的加密解密
    .Net Core使用 MiniProfiler 进行性能分析
  • 原文地址:https://www.cnblogs.com/Meng-NET/p/7152159.html
Copyright © 2020-2023  润新知