.net 中对象的 ICloneable 深层复制
ICloneable deepcopy of an object in .net
我正在尝试使用 ICloneable 添加一个深层复制方法到 classes 中,这些方法是使用 xsd.exe 从 xsd 自动生成的。我可以让它在一个简单的级别上工作,但是一旦对象嵌套,克隆方法就不起作用。
我很确定我在 DirectorReturnType 上的克隆方法有误 class 但我不知道如何修复它。
有人可以提供帮助吗?我在下面附上了潜艇和 classes:
Dim oDirRetType As New DirectorReturnType
Dim oDirPerType As New DirectorPersonType
Dim DirPerTypeT1 As New DirectorPersonType
Dim DirPerTypeT2 As New DirectorPersonType
Dim DirRetTypeT1 As New DirectorReturnType
Dim DirRetTypeT2 As New DirectorReturnType
Dim AROT1 As New AnnualReturnOfficer
Dim AROT2 As New AnnualReturnOfficer
这按预期工作,消息 "test1" 然后 "test2":
'Works
oDirPerType.Occupation = "test1"
DirRetTypeT1.Item = oDirPerType.Clone
oDirPerType.Occupation = "test2"
DirRetTypeT2.Item = oDirPerType.Clone
DirPerTypeT1 = DirRetTypeT1.Item
DirPerTypeT2 = DirRetTypeT2.Item
MsgBox(DirPerTypeT1.Occupation)
MsgBox(DirPerTypeT2.Occupation)
如果我随后添加一个类型为 AnnualRetunOfficer 的额外对象 AROTx,它会向 "Test2" 然后 "Test2" 发送消息。
'Doesnt Work
oDirPerType.Occupation = "test1"
oDirRetType.Item = oDirPerType
AROT1.Item = oDirRetType.Clone
oDirPerType.Occupation = "test2"
DirRetTypeT2.Item = oDirPerType
AROT2.Item = oDirRetType.Clone
DirRetTypeT1 = AROT1.Item
DirPerTypeT1 = DirRetTypeT1.Item
DirRetTypeT2 = AROT2.Item
DirPerTypeT2 = DirRetTypeT2.Item
MsgBox(DirPerTypeT1.Occupation)
MsgBox(DirPerTypeT2.Occupation)
导演类型:
Partial Public Class DirectorPersonType
Inherits PersonBaseType
Implements ICloneable
Private serviceAddressField As ServiceAddressType
Private dOBField As Date
Private nationalityField As String
Private occupationField As String
Private countryOfResidenceField As String
Private previousNamesField() As PreviousNameType
'''<remarks/>
Public Property ServiceAddress() As ServiceAddressType
Get
Return Me.serviceAddressField
End Get
Set(value As ServiceAddressType)
Me.serviceAddressField = value
End Set
End Property
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute(DataType:="date")> _
Public Property DOB() As Date
Get
Return Me.dOBField
End Get
Set(value As Date)
Me.dOBField = value
End Set
End Property
'''<remarks/>
Public Property Nationality() As String
Get
Return Me.nationalityField
End Get
Set(value As String)
Me.nationalityField = value
End Set
End Property
'''<remarks/>
Public Property Occupation() As String
Get
Return Me.occupationField
End Get
Set(value As String)
Me.occupationField = value
End Set
End Property
'''<remarks/>
Public Property CountryOfResidence() As String
Get
Return Me.countryOfResidenceField
End Get
Set(value As String)
Me.countryOfResidenceField = value
End Set
End Property
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute("PreviousNames")> _
Public Property PreviousNames() As PreviousNameType()
Get
Return Me.previousNamesField
End Get
Set(value As PreviousNameType())
Me.previousNamesField = value
End Set
End Property
Public Function Clone() As Object Implements System.ICloneable.Clone
Return New DirectorPersonType With {.CountryOfResidence = CountryOfResidence, .DOB = DOB, .Forename = Forename, .Nationality = Nationality, .Occupation = Occupation, .OtherForenames = OtherForenames, .PreviousNames = PreviousNames, .ServiceAddress = ServiceAddress, .Surname = Surname, .Title = Title}
End Function
End Class
DirectorReturnType:
Partial Public Class DirectorReturnType
Implements ICloneable
Private itemField As Object
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute("Corporate",
GetType(CorporateOfficerType)), _
System.Xml.Serialization.XmlElementAttribute("Person",
GetType(DirectorPersonType))> _
Public Property Item() As Object
Get
Return Me.itemField
End Get
Set(value As Object)
Me.itemField = Value
End Set
End Property
Public Function Clone() As Object Implements System.ICloneable.Clone
Return New DirectorReturnType With {.Item = Item}
End Function
您的克隆实际上并不是在制作一些变量的新副本,而是指向存储在原始 class 中的现有值。
即这两个变量:
Private serviceAddressField As ServiceAddressType
Private previousNamesField() As PreviousNameType
在克隆功能中需要特别注意。
调用 ME.MemberwiseClone
获取实例的新浅表副本是整洁的(也许不是完全标准的)。然后你必须单独处理你的非标准类型(数组,classes)并创建它们的新副本。
类似的东西(请纠正任何错误,但这是一般的想法)
Public Function Clone() As Object Implements ICloneable.Clone
Dim typClone As DirectorPersonType = Me.MemberwiseClone ' Shallow clone taken and new object created
Try
typClone.serviceAddressField = Me.serviceAddressField.Clone ' create a new copy with same value
typClone.previousNamesField.AddRange(Me.previousNamesField) ' create a new copy with the same values
' PreviousNamesField will need some work generating a new array
' let me know if you need more detail or a working example
' However, I have been corrected and will share that this method is
' definitely superior to AddRange, using LINQ to
' create a new list with a copy of the items
typClone.ListName = Me.ListName.Select(Function(x) x.Clone()).Cast(Of ClassName).ToList
Catch ex As Exception
' catch errors and handle here!
End Try
Return typClone
End Function
我正在尝试使用 ICloneable 添加一个深层复制方法到 classes 中,这些方法是使用 xsd.exe 从 xsd 自动生成的。我可以让它在一个简单的级别上工作,但是一旦对象嵌套,克隆方法就不起作用。
我很确定我在 DirectorReturnType 上的克隆方法有误 class 但我不知道如何修复它。
有人可以提供帮助吗?我在下面附上了潜艇和 classes:
Dim oDirRetType As New DirectorReturnType
Dim oDirPerType As New DirectorPersonType
Dim DirPerTypeT1 As New DirectorPersonType
Dim DirPerTypeT2 As New DirectorPersonType
Dim DirRetTypeT1 As New DirectorReturnType
Dim DirRetTypeT2 As New DirectorReturnType
Dim AROT1 As New AnnualReturnOfficer
Dim AROT2 As New AnnualReturnOfficer
这按预期工作,消息 "test1" 然后 "test2":
'Works
oDirPerType.Occupation = "test1"
DirRetTypeT1.Item = oDirPerType.Clone
oDirPerType.Occupation = "test2"
DirRetTypeT2.Item = oDirPerType.Clone
DirPerTypeT1 = DirRetTypeT1.Item
DirPerTypeT2 = DirRetTypeT2.Item
MsgBox(DirPerTypeT1.Occupation)
MsgBox(DirPerTypeT2.Occupation)
如果我随后添加一个类型为 AnnualRetunOfficer 的额外对象 AROTx,它会向 "Test2" 然后 "Test2" 发送消息。
'Doesnt Work
oDirPerType.Occupation = "test1"
oDirRetType.Item = oDirPerType
AROT1.Item = oDirRetType.Clone
oDirPerType.Occupation = "test2"
DirRetTypeT2.Item = oDirPerType
AROT2.Item = oDirRetType.Clone
DirRetTypeT1 = AROT1.Item
DirPerTypeT1 = DirRetTypeT1.Item
DirRetTypeT2 = AROT2.Item
DirPerTypeT2 = DirRetTypeT2.Item
MsgBox(DirPerTypeT1.Occupation)
MsgBox(DirPerTypeT2.Occupation)
导演类型:
Partial Public Class DirectorPersonType
Inherits PersonBaseType
Implements ICloneable
Private serviceAddressField As ServiceAddressType
Private dOBField As Date
Private nationalityField As String
Private occupationField As String
Private countryOfResidenceField As String
Private previousNamesField() As PreviousNameType
'''<remarks/>
Public Property ServiceAddress() As ServiceAddressType
Get
Return Me.serviceAddressField
End Get
Set(value As ServiceAddressType)
Me.serviceAddressField = value
End Set
End Property
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute(DataType:="date")> _
Public Property DOB() As Date
Get
Return Me.dOBField
End Get
Set(value As Date)
Me.dOBField = value
End Set
End Property
'''<remarks/>
Public Property Nationality() As String
Get
Return Me.nationalityField
End Get
Set(value As String)
Me.nationalityField = value
End Set
End Property
'''<remarks/>
Public Property Occupation() As String
Get
Return Me.occupationField
End Get
Set(value As String)
Me.occupationField = value
End Set
End Property
'''<remarks/>
Public Property CountryOfResidence() As String
Get
Return Me.countryOfResidenceField
End Get
Set(value As String)
Me.countryOfResidenceField = value
End Set
End Property
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute("PreviousNames")> _
Public Property PreviousNames() As PreviousNameType()
Get
Return Me.previousNamesField
End Get
Set(value As PreviousNameType())
Me.previousNamesField = value
End Set
End Property
Public Function Clone() As Object Implements System.ICloneable.Clone
Return New DirectorPersonType With {.CountryOfResidence = CountryOfResidence, .DOB = DOB, .Forename = Forename, .Nationality = Nationality, .Occupation = Occupation, .OtherForenames = OtherForenames, .PreviousNames = PreviousNames, .ServiceAddress = ServiceAddress, .Surname = Surname, .Title = Title}
End Function
End Class
DirectorReturnType:
Partial Public Class DirectorReturnType
Implements ICloneable
Private itemField As Object
'''<remarks/>
<System.Xml.Serialization.XmlElementAttribute("Corporate",
GetType(CorporateOfficerType)), _
System.Xml.Serialization.XmlElementAttribute("Person",
GetType(DirectorPersonType))> _
Public Property Item() As Object
Get
Return Me.itemField
End Get
Set(value As Object)
Me.itemField = Value
End Set
End Property
Public Function Clone() As Object Implements System.ICloneable.Clone
Return New DirectorReturnType With {.Item = Item}
End Function
您的克隆实际上并不是在制作一些变量的新副本,而是指向存储在原始 class 中的现有值。
即这两个变量:
Private serviceAddressField As ServiceAddressType
Private previousNamesField() As PreviousNameType
在克隆功能中需要特别注意。
调用 ME.MemberwiseClone
获取实例的新浅表副本是整洁的(也许不是完全标准的)。然后你必须单独处理你的非标准类型(数组,classes)并创建它们的新副本。
类似的东西(请纠正任何错误,但这是一般的想法)
Public Function Clone() As Object Implements ICloneable.Clone
Dim typClone As DirectorPersonType = Me.MemberwiseClone ' Shallow clone taken and new object created
Try
typClone.serviceAddressField = Me.serviceAddressField.Clone ' create a new copy with same value
typClone.previousNamesField.AddRange(Me.previousNamesField) ' create a new copy with the same values
' PreviousNamesField will need some work generating a new array
' let me know if you need more detail or a working example
' However, I have been corrected and will share that this method is
' definitely superior to AddRange, using LINQ to
' create a new list with a copy of the items
typClone.ListName = Me.ListName.Select(Function(x) x.Clone()).Cast(Of ClassName).ToList
Catch ex As Exception
' catch errors and handle here!
End Try
Return typClone
End Function