索引:

目录索引

一、说明

  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. [认证授权] 4.OIDC(OpenId Connect)身份认证授权(核心部分)

    0 目录 认证授权系列:http://www.cnblogs.com/linianhui/category/929878.html 1 什么是OIDC? 看一下官方的介绍(http://openid. ...

  2. 关于PHP高并发抢购系统设计

    内容并发抢购系统注意事项高并发架构设计描述程序端核心代码实现订单流程mysql 端并发解决方案注意事项(1)高并发环境下,对于服务器cup.内存.网络宽带使用率会瞬间暴涨,需要注意对同服务器上其他应用 ...

  3. SpringMVC form:form的一个错误(没有传到前台绑定类)

    SpringMVC form:form的一个错误(没有传到前台绑定类) 报错信息: Neither BindingResult nor plain target object for bean nam ...

  4. Spring 4学习——问题与注意事项(一)

    1.Spring项目依赖的jar包有5个: 2.applicationContext.xml文件中,如下bean的property的name值对应的是HelloWorld类中的setter方法,即na ...

  5. CSS实现文字和图片的水平垂直居中

    关于文字和图片的水平垂直居中,在前端界绝对算是一个老生常谈的问题了,尤其是垂直居中,什么千奇百怪的解法都能想的出来.下面我就总结一些比较常用的方法: 一.文本的水平垂直居中: 1.水平居中: 是不是很 ...

  6. 原生和jQuery的ajax用法

    jQuery的ajax方法: $.ajax({ url:'/comm/test1.php', type:'POST', //GET async:true, //或false,是否异步 data:{ n ...

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

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

  8. Unity3D常用 API 之实例化与销毁

    1.实例化游戏物体 1.1.游戏中的案例介绍 在很多 MMORPG 类的游戏中都有类似于“金钱副本”的副本关卡.在这类副 本中通常都是限定一个时间,在这个时间内玩家可以尽情的破坏,然后收集金钱. 分析 ...

  9. Nmap脚本引擎原理

    Nmap脚本引擎原理 一.NSE介绍 虽然Nmap内嵌的服务于版本探测已足够强大,但是在某些情况下我们需要多伦次的交互才能够探测到服务器的信息,这时候就需要自己编写NSE插件实现这个功能.NSE插件能 ...

  10. WPF: 实现 ScrollViewer 滚动到指定控件处

    在前端 UI 开发中,有时,我们会遇到这样的需求:在一个 ScrollViewer 中有很多内容,而我们需要实现在执行某个操作后能够定位到其中指定的控件处:这很像在 HTML 页面中点击一个链接后定位 ...