VB.NET 序列化深拷贝

浅拷贝:引用成员在被拷贝时,仅被复制原对象中引用成员的地址引用到新生对象,使用复制后的新对象、

若更改引用成员内的值可能会影响源对象

深拷贝:引用成员在被拷贝时,深入拷贝所有引用成员,而不是拷贝地址引用那样简单、新对象中包含的

所有成员、全部是新生对象在使用复制后的新对象不会影响源对象

浅拷贝在.NET中通常使用,System::Object::MemberwiseClone 直接进行快速拷贝、

    <__DynamicallyInvokable(), SecuritySafeCritical()>
    <MethodImpl(MethodImplOptions.InternalCall)>
    Protected Function MemberwiseClone() As Object

下面是一个用于被序列化复制的类,“Deep Cory 深拷贝”、“Shallow Copy 浅拷贝”

需要被序列化的类,一定需要在类的顶部添加上<Serializable>特性 否则无法使用

如果不允许成员被序列化,应该在成员上方添加<NonSerialized>特性即可、

    <Serializable>
    Public Class DeepCopy

        Private mValue As Integer

        Public Property Value As Integer
            Get
                Return Me.mValue
            End Get
            Set(value As Integer)
                Me.mValue = value
            End Set
        End Property

    End Class
   

下面的代码主要是一个调用测试被序列化复制后修改成员中的值是否会影响源对象的成员

    Sub Main()
        Dim x = New DeepCopy()
        x.Value = 250
        Dim y As DeepCopy = Clone(x)
        y.Value = 100
        Console.WriteLine("X={0}, Y={1}", x.Value, y.Value)
        Console.ReadKey(False)
    End Sub

即使是浅拷贝上面的代码也不会影响源对象中成员,我在上面提到只有引用成员会被影响

而值类型成员不会相互影响、

浅拷贝引用单个引用成员指针依旧需要消耗足足4~8个字节、受处理器与开发平台制约

    Public Function Clone(ByVal obj) As Object
        Using ms As MemoryStream = New MemoryStream()
            Dim fm = New BinaryFormatter()
            fm.Serialize(ms, obj)
            ms.Seek(0, SeekOrigin.Begin)
            Return fm.Deserialize(ms)
        End Using
    End Function

上面是序列化深度复制的一个代码,创建内存流对象 MemoryStream 且创建

二进制序列化对象BinaryFormatter

BinaryFormatter::Serialize // 序列化

BinaryFormatter::Deserialize // 反序列化

把对象序列化后,Stream::Seek在结束位置,我们需要移动位置到流的开始处

才可以反序列化对象 否则会产生错误

    Public Function IL_Clone(ByVal obj) As Object
        Dim dm = New DynamicMethod("Clone", GetType(Object), {GetType(Object)})
        Dim il = dm.GetILGenerator()

        Dim il_0033 = il.DefineLabel()
        Dim il_DE84 = il.DeclareLocal(GetType(MemoryStream))
        Dim il_FA10 = il.DeclareLocal(GetType(BinaryFormatter))
        Dim il_BCC2 = il.DeclareLocal(GetType(Object))
        Dim iL_CS10 = il.DeclareLocal(GetType(Object))

        il.Emit(OpCodes.Newobj, GetType(MemoryStream).GetConstructor({}))
        il.Emit(OpCodes.Stloc_0)
        il.Emit(OpCodes.Newobj, GetType(BinaryFormatter).GetConstructor({}))
        il.Emit(OpCodes.Stloc_1)
        il.Emit(OpCodes.Ldloc_1)
        il.Emit(OpCodes.Ldloc_0)
        il.Emit(OpCodes.Ldarg_0)
        il.Emit(OpCodes.Callvirt, GetType(BinaryFormatter).GetMethod("Serialize", {GetType(MemoryStream), GetType(Object)}))
        il.Emit(OpCodes.Ldloc_0)
        il.Emit(OpCodes.Ldc_I4_0)
        il.Emit(OpCodes.Conv_I8)
        il.Emit(OpCodes.Ldc_I4_0)
        il.Emit(OpCodes.Callvirt, GetType(MemoryStream).GetMethod("Seek", {GetType(Int64), GetType(SeekOrigin)}))
        il.Emit(OpCodes.Pop)
        il.Emit(OpCodes.Ldloc_1)
        il.Emit(OpCodes.Ldloc_0)
        il.Emit(OpCodes.Callvirt, GetType(BinaryFormatter).GetMethod("Deserialize", {GetType(MemoryStream)}))
        il.Emit(OpCodes.Stloc_2)
        il.Emit(OpCodes.Ldloc_0)
        il.Emit(OpCodes.Callvirt, GetType(MemoryStream).GetMethod("Close", {}))
        il.Emit(OpCodes.Ldloc_2)
        il.Emit(OpCodes.Stloc_3)
        il.Emit(OpCodes.Br_S, il_0033)
        il.MarkLabel(il_0033)
        il.Emit(OpCodes.Ldloc_3)
        il.Emit(OpCodes.Ret)

        Return dm.Invoke(dm, {obj})
    End Function

上面是通过内嵌IL代码,实现对象的深拷贝 本质上是上上面代码的一个

机器写法 功能是相同的 做法也是相同的 只是一个调用Using一个Close

差异性并不是很大 依赖的命名空间

Imports System
Imports System.IO
Imports System.Reflection.Emit
Imports System.Runtime.Serialization.Formatters.Binary

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-04 00:52:53

VB.NET 序列化深拷贝的相关文章

一步步分析Java深拷贝的两种方式-clone和序列化

今天遇到一道面试题,询问深拷贝的两种方法.主要就是clone方法和序列化方法.今天就来分析一下这两种方式如何实现深拷贝.如果想跳过解析的朋友,直奔"重点来了!"寻找答案. clone方法 例1:我们不妨建立一个Exam对象 考试类Exam.java文件 public class Exam implements Cloneable { private int examId; private String examName; public Exam() { } public Exam(in

c# 深拷贝 浅拷贝

浅拷贝对引用类型只拷贝地址,拷贝前后共享一块内存区域.深拷贝就是所有的东西全部重新有一份,没有共享存在,推荐使用序列化深拷贝. using System; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace ConsoleApplication1 { internal class Program { [Serializable] public class TV { public TV()

C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝

原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一种创建型模式,它关注的是大量相同或相似对象的创建问题.应用原型模式就是建立一个原型,然后通过对原型来进行复制的方法,来产生一个和原型相同或相似的新对象,或者说用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象. 模式中的角色 抽象原型类(Abstract Prototype):提供一个克

App的网络环境测试和性能优化

1. 网络环境测试一般是先用网络损伤模拟仪或mock工具模拟常见的七种损伤和5种网络环境,然后再国内外城市采样的方式(带宽和延时)组合测试生成报告, 下面是一些统计图 2. 采样点的选择一般都是根据自己server收集的用户信息.如果新app就要参考近品/竞品或第三方的统计数据拍脑袋 3. 从测试的角度,应该建立实时监控的web portal.其实测试的目的除了保证产品发布的质量.更重要的是为优化提供依据,所以report最后一部分都是issue list 和optmize advice,当然测

Effective Java 读书笔记

1.当有多个参数时,使用构建器模式 常用的场景是,查询时,有多个参数.因此构建查询参数对象时,考虑使用Builder模式. public class QueryBuilder { //查询的每个参数,不需要set方法 private String userName; private String mobile; private int cityId; private int pageNum; private int pageSize; //提供一个Builder实例 public static

PHP设计模式之工厂模式和原型模式

这两个模式都是针对对象创建和复用的,只是一种设计风格,在创建对象的,随时都可以改进现有的代码.毕竟老代码很多地方不容易更改了,所以这两个模式一般适合新加进去,比较容易创建对象或者使用新对象 再者就是...算了 我想说的就是JS,把原型做的炉火纯青,我一直很痴迷,很多原型都深深的嵌入到语言的内核. 推荐那本书<你不知道的JS> 上代码 <?php interface Prototype{ public function shallowCopy(); public function deep

java设计模式 - 原型(干货)

深度讲解23种设计模式,力争每种设计模式都刨析到底.废话不多说,开始第二种设计模式 - 原型. 一.为什么有原型模式 当一个类需要克隆的时候,我们总不希望new一个对象,然后逐个属性去设置值. 这个时候,我们亟需一种 高效的对象copy方法,原型设计模式应运而生. 二.原型设计模式写法 原型设计模式实现: public class Person implements Cloneable { private String userName; private String sex; private

Java 深拷贝浅拷贝 与 序列化

一.浅拷贝.深拷贝 浅拷贝会对对象中的成员变量进行拷贝:如果是基本类型,拷贝的就是基本类型的值:如果属性是内存地址(引用类型),拷贝的就是内存地址 : 深拷贝,除了基本类型外,引用类型所引用的对象也会进行拷贝:(引用的对象只要求浅拷贝即可:若要深层拷贝,一般可利用序列化和反序列化来实现,也可手动实现各级引用对象的深层拷贝:) 二.实现: 浅拷贝:实现Cloneable接口,重写clone()方法,在clone()调用父类super.clone()即可: 深拷贝:1. 实现Cloneable接口,

序列化实现 深拷贝

1 private static Object DeepClone(Object original) 2 { 3 using (MemoryStream stream = new MemoryStream()) 4 { 5 BinaryFormatter formatter = new BinaryFormatter(); 6 7 formatter.Context = new StreamingContext(StreamingContextStates.Clone); 8 9 formatt