索引:

目录索引

一、说明

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

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

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

二、代码

  代码如下:

  核心类  NonSerialiazableTypeSurrogateSelector :  

     /// <summary>
/// 深度复制 / Surrogate
/// </summary>
public class NonSerialiazableTypeSurrogateSelector : ISerializationSurrogate, ISurrogateSelector
{
/// <summary>
/// _nextSelector
/// </summary>
ISurrogateSelector _nextSelector; #region ISerializationSurrogate / 实现
/// <summary>
/// GetObjectData
/// </summary>
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
{
FieldInfo[] fieldInfos = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var fi in fieldInfos)
{
if (IsKnownType(fi.FieldType))
{
info.AddValue(fi.Name, fi.GetValue(obj));
}
else if (fi.FieldType.IsClass)
{
info.AddValue(fi.Name, fi.GetValue(obj));
}
}
} /// <summary>
/// SetObjectData
/// </summary>
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
{
FieldInfo[] fieldInfos = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var fi in fieldInfos)
{
if (IsKnownType(fi.FieldType))
{
if (IsNullableType(fi.FieldType))
{
Type argumentValueForTheNullableType = GetFirstArgumentOfGenericType(fi.FieldType);
fi.SetValue(obj, info.GetValue(fi.Name, argumentValueForTheNullableType));
}
else
{
fi.SetValue(obj, info.GetValue(fi.Name, fi.FieldType));
}
}
else if (fi.FieldType.IsClass)
{
fi.SetValue(obj, info.GetValue(fi.Name, fi.FieldType));
}
}
return obj;
}
#endregion #region ISurrogateSelector / 实现
/// <summary>
/// ChainSelector
/// </summary>
public void ChainSelector(ISurrogateSelector selector)
{
this._nextSelector = selector;
} /// <summary>
/// GetNextSelector
/// </summary>
public ISurrogateSelector GetNextSelector()
{
return _nextSelector;
} /// <summary>
/// GetSurrogate
/// </summary>
public ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector)
{
if (IsKnownType(type))
{
selector = null;
return null;
}
else if (type.IsClass || type.IsValueType)
{
selector = this;
return this;
}
else
{
selector = null;
return null;
}
}
#endregion #region 私有方法
/// <summary>
/// 是否为已知类型 / String,Primitive,Serializable
/// </summary>
private bool IsKnownType(Type type)
{
return type == typeof(string) || type.IsPrimitive || type.IsSerializable;
} /// <summary>
/// 是否为可空类型
/// </summary>
private bool IsNullableType(Type type)
{
if (type.IsGenericType)
{
return type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
return false;
} /// <summary>
/// GetFirstArgumentOfGenericType
/// </summary>
private Type GetFirstArgumentOfGenericType(Type type)
{
return type.GetGenericArguments()[];
}
#endregion
}

NonSerialiazableTypeSurrogateSelector.cs

  扩展类 ObjectMethodExtensions :

     public static class ObjectMethodExtensions
{
/// <summary>
/// 深度复制 (值类型/包装类型/引用类型/序列化/非序列化/标识序列化/非标识序列化,皆可深度复制)
/// </summary>
public static T DeepClone<T>(this T obj)
{
var result = default(T);
try
{
IFormatter formatter = new BinaryFormatter();
formatter.SurrogateSelector = new SurrogateSelector();
formatter.SurrogateSelector.ChainSelector(new NonSerialiazableTypeSurrogateSelector());
var ms = new MemoryStream();
formatter.Serialize(ms, obj);
ms.Position = ;
result = (T)formatter.Deserialize(ms);
}
catch (Exception ex)
{
throw new Exception("方法:DeepClone<T>(this T obj)出错.", ex);
}
return result;
}
}

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

【Stack Overflow -- 原创加工、原创整理、生产实战】-- 深度复制的更多相关文章

  1. [SQL SERVER系列]工作经常使用的SQL整理,实战篇(一)[原创]

    工作经常使用的SQL整理,实战篇,地址一览: 工作经常使用的SQL整理,实战篇(一) 工作经常使用的SQL整理,实战篇(二) 工作经常使用的SQL整理,实战篇(三) 目录概览: 1.数据库 2.表 3 ...

  2. [SQL SERVER系列]工作经常使用的SQL整理,实战篇(三)[原创]

    工作经常使用的SQL整理,实战篇,地址一览: 工作经常使用的SQL整理,实战篇(一) 工作经常使用的SQL整理,实战篇(二) 工作经常使用的SQL整理,实战篇(三) 接着本系列前面两篇继续讨论. 有时 ...

  3. [SQL SERVER系列]工作经常使用的SQL整理,实战篇(二)[原创]

    工作经常使用的SQL整理,实战篇,地址一览: 工作经常使用的SQL整理,实战篇(一) 工作经常使用的SQL整理,实战篇(二) 工作经常使用的SQL整理,实战篇(三) 接着上一篇“工作经常使用的SQL整 ...

  4. [原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(后篇)

    原文:[原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(后篇) .NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(后篇) 前言:接着上篇来. 系列文章链接: [ ...

  5. [原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略

    原文:[原创].NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略 .NET 业务框架开发实战之九 Mapping属性原理和验证规则的实现策略 前言:之前的讨论一直关注在怎么从D ...

  6. [原创].NET 业务框架开发实战之八 业务层Mapping的选择策略

    原文:[原创].NET 业务框架开发实战之八 业务层Mapping的选择策略 .NET 业务框架开发实战之八 业务层Mapping的选择策略 前言:在上一篇文章中提到了mapping,感觉很像在重新实 ...

  7. [原创].NET 业务框架开发实战之七 业务层初步构想

    原文:[原创].NET 业务框架开发实战之七 业务层初步构想 .NET 业务框架开发实战之七 业务层初步构想 前言:本篇主要讲述如何把DAL和BLL衔接起来. 本篇议题如下: 1.       DAL ...

  8. [原创].NET 业务框架开发实战之六 DAL的重构

    原文:[原创].NET 业务框架开发实战之六 DAL的重构 .NET 业务框架开发实战之六 DAL的重构 前言:其实这个系列还是之前的".NET 分布式架构开发实战 ",之所以改了 ...

  9. [原创].NET 分布式架构开发实战五 Framework改进篇

    原文:[原创].NET 分布式架构开发实战五 Framework改进篇 .NET 分布式架构开发实战五 Framework改进篇 前言:本来打算这篇文章来写DAL的重构的,现在计划有点改变.之前的文章 ...

随机推荐

  1. mysqldump备份还原mysql

    本文实现在mysql 5.7 解压版为例子 1.在window上简单试下一个例子 1.使用管理员权限打开cmd命名行,并切换到mysqldump执行程序下

  2. Java反射机制剖析(一)-定义和API

    1.     什么是Java反射机制 Java的反射机制是在程序运行时,能够完全知道任何一个类,及其它的属性和方法,并且能够任意调用一个对象的属性和方法.这种运行时的动态获取就是Java的反射机制.其 ...

  3. java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制

    ClassLoader的工作机制 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有Bootstrap ClassLoader. ...

  4. SmartCoder每日站立会议10

    站立会议内容: 准备为上交第一阶段项目进行加班,将各个页面联系起来,静态地图变为动态转换,考虑地图全屏或者是小屏即消息展示方式 1.站立会议照片:      2.任务展板: 3.燃尽图:

  5. 深度解析PHP数组函数array_chunk

    array_chunk是PHP中的一个数组分割函数,是将一个数组分割为多个数组块 我们可以把它理解卖豆腐的商人把一整块大豆腐切割为一个一个的小块来进行售卖 这个函数需要三个参数: 被切割的数组(必需) ...

  6. VR全景智慧城市-提前进入商家观景,涵盖实体行业

    互联网发展的迅猛势头,让很多的实体商家翻了个大跟头,更有言说,未来的大街小巷根本见不到逛街的人,可是线上商城相继曝出的假货谁来买单?相比之下眼见为实更让消费者心里觉得踏实.所以,全景智慧城市更能满足大 ...

  7. Vulkan Tutorial 08 交换链

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 在这一章节,我们了解一下将渲染图像提交到屏幕的基本机制.这种机制成为交换链,并且需要 ...

  8. Coursera 机器学习笔记(三)

    主要为第四周.第五周课程内容:神经网络 神经网络模型引入 之前学习的线性回归还是逻辑回归都有个相同缺点就是:特征太多会导致计算量太大.如100个变量,来构建一个非线性模型.即使只采用两两特征组合,都会 ...

  9. winserver2008r2 + iis7安装django

    同样网上看了无数教程,但总是这个错一点那个错一点点的结果就一直没成功然后逞着今天空了那么一下午下定决定再折腾下把django跑起来,解决了静态文件问题为了方便以后复制粘贴,就全文字,嘿嘿 废话不说,接 ...

  10. asp.net core 教程(七)-异常处理、静态文件

    Asp.Net Core-异常处理 Asp.Net Core-异常处理 在这一章,我们将讨论异常和错误处理.当 ASP.NET Core应用程序中发生错误时,您可以以各种不同的方式来处理.让我们来看看 ...