加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

VB.NET 序列化深拷贝

发布时间:2020-12-17 07:44:57 所属栏目:百科 来源:网络整理
导读:浅拷贝: 引用成员在被拷贝时,仅被复制原对象中引用成员的地址引用到新生对象,使用复制后的新对象、 若更改引用成员内 的值 可能 会 影响源对象 深拷贝: 引用成员在被拷贝时,深入拷贝所有引用成员,而不是拷贝地址引用那样简单、新对象中包含的 所有成员

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

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

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

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

浅拷贝在.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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读