VB.NET || How To Copy All Properties & Fields From One Object To Another Using VB.NET
The following is a module with functions which demonstrates how to copy all properties and fields from one object to another using VB.NET.
The function demonstrated on this page is a generic extension method which uses reflection to copy all the matching properties and fields from one object to another.
This function works on both structure and class object fields and properties.
The two objects do not have to be the same type. Only the matching properties and fields are copied.
1. Copy Properties & Fields
The example below demonstrates the use of ‘Utils.Objects.CopyPropsTo‘ to copy all the matching properties and fields from the source object to the destination object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
' Copy Properties & Fields Imports Utils.Objects Public Class Part Public Property PartName As String Public Property PartId As Integer End Class Public Structure Part2 Public Property PartName As String Public PartId As Integer End Structure ' Declare source object Dim part1 = New Part With { .PartName = "crank arm", .PartId = 1234 } ' Declare destination object Dim part2 = New Part2 ' Copy matching properties and fields to destination part1.CopyPropsTo(part2) ' Display information Debug.Print($"{part2.PartId} - {part2.PartName}") ' expected output: ' 1234 - crank arm |
2. Utils Namespace
The following is the Utils Namespace. Include this in your project to start using!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
' ============================================================================ ' Author: Kenneth Perkins ' Date: Nov 22, 2020 ' Taken From: http://programmingnotes.org/ ' File: Utils.vb ' Description: Handles general utility functions ' ============================================================================ Option Strict On Option Explicit On Namespace Global.Utils Namespace Objects Public Module modObjects ''' <summary> ''' Copies all the matching properties and fields from 'source' to 'destination' ''' </summary> ''' <param name="source">The source object to copy from</param> ''' <param name="destination">The destination object to copy to</param> <Runtime.CompilerServices.Extension()> Public Sub CopyPropsTo(Of T1, T2)(source As T1, ByRef destination As T2) Dim sourceMembers = GetMembers(source.GetType) Dim destinationMembers = GetMembers(destination.GetType) ' Copy data from source to destination For Each sourceMember In sourceMembers If Not CanRead(sourceMember) Then Continue For End If Dim destinationMember = destinationMembers.FirstOrDefault(Function(x) x.Name.ToLower = sourceMember.Name.ToLower) If destinationMember Is Nothing _ OrElse Not CanWrite(destinationMember) Then Continue For End If SetObjectValue(destination, destinationMember, GetMemberValue(source, sourceMember)) Next End Sub Private Sub SetObjectValue(Of T)(ByRef obj As T, member As System.Reflection.MemberInfo, value As Object) ' Boxing method used for modifying structures Dim boxed = If(obj.GetType.IsValueType, CType(obj, Object), obj) SetMemberValue(boxed, member, value) obj = CType(boxed, T) End Sub Private Sub SetMemberValue(Of T)(ByRef obj As T, member As System.Reflection.MemberInfo, value As Object) If IsProperty(member) Then Dim prop = CType(member, System.Reflection.PropertyInfo) If prop.SetMethod IsNot Nothing Then prop.SetValue(obj, value) End If ElseIf IsField(member) Then Dim field = CType(member, System.Reflection.FieldInfo) field.SetValue(obj, value) End If End Sub Private Function GetMemberValue(obj As Object, member As System.Reflection.MemberInfo) As Object Dim result As Object = Nothing If IsProperty(member) Then Dim prop = CType(member, System.Reflection.PropertyInfo) result = prop.GetValue(obj, If(prop.GetIndexParameters.Count = 1, New Object() {Nothing}, Nothing)) ElseIf IsField(member) Then Dim field = CType(member, System.Reflection.FieldInfo) result = field.GetValue(obj) End If Return result End Function Private Function CanWrite(member As System.Reflection.MemberInfo) As Boolean Return If(IsProperty(member), CType(member, System.Reflection.PropertyInfo).CanWrite, IsField(member)) End Function Private Function CanRead(member As System.Reflection.MemberInfo) As Boolean Return If(IsProperty(member), CType(member, System.Reflection.PropertyInfo).CanRead, IsField(member)) End Function Private Function IsProperty(member As System.Reflection.MemberInfo) As Boolean Return IsType(member.GetType, GetType(System.Reflection.PropertyInfo)) End Function Private Function IsField(member As System.Reflection.MemberInfo) As Boolean Return IsType(member.GetType, GetType(System.Reflection.FieldInfo)) End Function Private Function IsType(type As System.Type, targetType As System.Type) As Boolean Return type.Equals(targetType) OrElse type.IsSubclassOf(targetType) End Function Private Function GetMembers(type As System.Type) As List(Of System.Reflection.MemberInfo) Dim flags = System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.Public _ Or System.Reflection.BindingFlags.NonPublic Dim members = New List(Of System.Reflection.MemberInfo) members.AddRange(type.GetProperties(flags)) members.AddRange(type.GetFields(flags)) Return members End Function End Module End Namespace End Namespace ' http://programmingnotes.org/ |
3. More Examples
Below are more examples demonstrating the use of the ‘Utils‘ Namespace. Don’t forget to include the module when running the examples!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
' ============================================================================ ' Author: Kenneth Perkins ' Date: Nov 22, 2020 ' Taken From: http://programmingnotes.org/ ' File: Program.vb ' Description: The following demonstrates the use of the Utils Namespace ' ============================================================================ Option Strict On Option Explicit On Imports System Imports Utils.Objects Module Program Public Class Part Public Property PartName As String Public PartId As Integer? End Class Public Structure Part2 Public Property PartName As String Public PartId As Integer End Structure Sub Main(args As String()) Try ' Declare source object Dim part1 = New Part With { .PartName = "crank arm", .PartId = 1234 } ' Declare destination object Dim part2 = New Part2 ' Copy matching properties and fields to destination part1.CopyPropsTo(part2) ' Display information Display($"{part2.PartId} - {part2.PartName}") Catch ex As Exception Display(ex.ToString) Finally Console.ReadLine() End Try End Sub Public Sub Display(message As String) Console.WriteLine(message) Debug.Print(message) End Sub End Module ' http://programmingnotes.org/ |
QUICK NOTES:
The highlighted lines are sections of interest to look out for.
The code is heavily commented, so no further insight is necessary. If you have any questions, feel free to leave a comment below.
Leave a Reply