属性 使用反射递归在两个对象之间复制

Property Copying Between Two Objects using Reflection Recursive

我正在尝试将源对象的 属性 值深度复制到目标对象的同名 属性。 我遇到 运行 的问题是,如果源 属性 是一个集合,在这种情况下是 List(of integer)。它将复制它作为参考,而不是预期的独立副本,并且可以在输出结果中看到。 我计划为每个集合 属性 递归调用 Copy 函数,以便对该对象进行深层复制。 L'ii 还添加了一些关联代码。

我遇到的问题是在进行类型比较时无法检测到 List(of) 对象 2) 尽管这在进行 Int16 类型比较时有效 1) 当我比较 type.Name 3)

时,我可以让它工作

这 3) 是否足够强大,或者是否有办法使 2) 工作?

Output:
Unchanged
Source.ID:1 Dest.ID:1
Source.Description:Source Description   Dest.Description:Source Description
Source.Links(0):10  Dest.Links(0):10
Source.Links(1):11  Dest.Links(1):11
changed
Source.ID:1 Dest.ID:100
Source.Description:Source Description   Dest.Description:Dest Description
Source.Links(0):50  Dest.Links(0):50
Source.Links(1):11  Dest.Links(1):11
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        Dim Source As New DataClass
        Dim SourceLinks As New List(Of Integer)({10, 11, 12})
        Source.ID = 1
        Source.Description = "Source Description"
        Source.Links = SourceLinks

        Dim Dest As New DataClass
        PropertyCopier(Of DataClass, DataClass).Copy(Source, Dest)

        Debug.Print("Unchanged")
        Debug.Print("Source.ID:" & Source.ID & vbTab & "Dest.ID:" & Dest.ID)
        Debug.Print("Source.Description:" & Source.Description & vbTab & "Dest.Description:" & Dest.Description)
        Debug.Print("Source.Links(0):" & Source.Links(0) & vbTab & "Dest.Links(0):" & Dest.Links(0))
        Debug.Print("Source.Links(1):" & Source.Links(1) & vbTab & "Dest.Links(1):" & Dest.Links(1))

        Debug.Print("changed")
        Dest.ID = 100
        Dest.Description = "Dest Description"
        Dest.Links(0) = 50
        Debug.Print("Source.ID:" & Source.ID & vbTab & "Dest.ID:" & Dest.ID)
        Debug.Print("Source.Description:" & Source.Description & vbTab & "Dest.Description:" & Dest.Description)
        Debug.Print("Source.Links(0):" & Source.Links(0) & vbTab & "Dest.Links(0):" & Dest.Links(0))
        Debug.Print("Source.Links(1):" & Source.Links(1) & vbTab & "Dest.Links(1):" & Dest.Links(1))
    End Sub
End Class
Public Class DataClass
    Public Property ID As Int16
    Public Property Description As String
    Public Property Links As List(Of Integer)
End Class
Public Class PropertyCopier(Of TSource As Class, TDestination As Class)
    Public Shared Sub Copy(ByVal Source As TSource, ByVal Destination As TDestination)
        Dim SourceProperties = Source.[GetType]().GetProperties()
        Dim DestinationProperties = Destination.[GetType]().GetProperties()

        For Each SourceProperty In SourceProperties
            For Each DestinationProperty In DestinationProperties
                If SourceProperty.Name = DestinationProperty.Name AndAlso SourceProperty.PropertyType = DestinationProperty.PropertyType Then
                    If SourceProperty.PropertyType = GetType(Int16) Then
                        '1) Correctly detects the property type as a integer
                    ElseIf SourceProperty.PropertyType = GetType(List(Of)) Then
                        '2) Does not detect the List(of ) type
                    ElseIf SourceProperty.PropertyType.Name = GetType(List(Of)).Name Then
                        '3) Correctly detects the property type as List(of )
                    End If
                    If SourceProperty.CanWrite Then DestinationProperty.SetValue(Destination, SourceProperty.GetValue(Source))
                    Exit For
                End If
            Next
        Next
    End Sub
End Class

问题是您的对象的泛型类型参数被设置为特定的东西,例如您将 List(Of String)List(Of) 进行比较,但它们并不相同。您需要做的是从该泛型类型中获取泛型类型定义,即

ElseIf SourceProperty.PropertyType.IsGenericType AndAlso
       SourceProperty.PropertyType.GetGenericTypeDefinition() Is GetType(List(Of)) Then

注意 Is 的正确用法,而不是 =

根据您需要使用的内容,您可能还希望寻找接口兼容性而不是完全相等。您可以使用 Type.IsAssignableFrom 来做到这一点。我有类似的代码来查找这样的列表:

If sourceProperty.PropertyType.IsGenericType _
   AndAlso GetType(IList).IsAssignableFrom(sourceProperty.PropertyType) Then
    '...
End If

(基于之前的回答)

如果需要,您可以使用例如sourceProperty.PropertyType.GenericTypeArguments(0).