Hello All,
I am in need of some assistance in improving a piece of code. It’s a single class that is part of a larger project which replicates windows device manager. The code has several functions which are repetitive. I would like to find a way to consolidate these into a single function.

' Refactored VB.NET implementation of Device class and its dependencies

Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Windows.Forms
Imports Microsoft.Win32

Public NotInheritable Class Device

   Private ReadOnly _deviceInfoset As IntPtr
   Private ReadOnly _deviceInfoData As DeviceInstanceInfo
   Private ReadOnly _properties As Dictionary(Of DevicePropertyID, Object)
   Private ReadOnly _memoryRanges As Lazy(Of IList(Of DeviceMemoryRange))
   Private ReadOnly _portRanges As Lazy(Of IList(Of DevicePortRange))
   Private ReadOnly _dmaRanges As Lazy(Of IList(Of DeviceDMARange))
   Private ReadOnly _irqRanges As Lazy(Of IList(Of DeviceIRQRange))
   Private ReadOnly _drivers As Lazy(Of IList(Of DeviceDriver))

   Private _flags As DeviceInstanceFlags
   Private _problem As DeviceInstanceProblem

   Public Sub New(hInfoSet As IntPtr, instanceInfo As DeviceInstanceInfo)
       _deviceInfoset = hInfoSet
       _deviceInfoData = instanceInfo
       _properties = New Dictionary(Of DevicePropertyID, Object)()
       _memoryRanges = New Lazy(Of IList(Of DeviceMemoryRange))(AddressOf EnumerateMemoryResources)
       _portRanges = New Lazy(Of IList(Of DevicePortRange))(AddressOf EnumeratePortResources)
       _dmaRanges = New Lazy(Of IList(Of DeviceDMARange))(AddressOf EnumerateDMAResources)
       _irqRanges = New Lazy(Of IList(Of DeviceIRQRange))(AddressOf EnumerateIRQResources)
       _drivers = New Lazy(Of IList(Of DeviceDriver))(AddressOf EnumerateDrivers)

       InitializeDeviceStatus()
   End Sub

   Private Sub InitializeDeviceStatus()
       If NativeMethods.CM_Get_DevNode_Status(_flags, _problem, _deviceInfoData.InstanceID, 0) = ConfigResult.Success Then
           If (_flags And DeviceInstanceFlags.HAS_PROBLEM) = 0 Then
               _problem = DeviceInstanceProblem.NO_PROBLEM
           End If
       Else
           _flags = DeviceInstanceFlags.HAS_PROBLEM
           _problem = DeviceInstanceProblem.NO_PROBLEM
       End If
   End Sub

   Private Function GetRegistryProperty(Of T)(propertyID As DevicePropertyID, expectedType As RegistryValueKind) As T
       Dim buffer(1023) As Byte
       Dim requiredSize As Integer
       Dim dataType As RegistryValueKind

       If NativeMethods.SetupDiGetDeviceRegistryPropertyW(_deviceInfoset, _deviceInfoData, propertyID, dataType, buffer, buffer.Length, requiredSize) Then
           If dataType <> expectedType Then
               Throw New InvalidCastException($"Unexpected registry value type: {dataType}")
           End If

           Return DirectCast(Convert.ChangeType(buffer, GetType(T)), T)
       Else
           Throw New InvalidOperationException($"Failed to retrieve property {propertyID}.")
       End If
   End Function

   Private Function EnumerateMemoryResources() As IList(Of DeviceMemoryRange)
       Dim resources As New List(Of DeviceMemoryRange)()
       ' Implementation logic for enumerating memory resources
       Return resources
   End Function

   Private Function EnumeratePortResources() As IList(Of DevicePortRange)
       Dim resources As New List(Of DevicePortRange)()
       ' Implementation logic for enumerating port resources
       Return resources
   End Function

   Private Function EnumerateDMAResources() As IList(Of DeviceDMARange)
       Dim resources As New List(Of DeviceDMARange)()
       ' Implementation logic for enumerating DMA resources
       Return resources
   End Function

   Private Function EnumerateIRQResources() As IList(Of DeviceIRQRange)
       Dim resources As New List(Of DeviceIRQRange)()
       ' Implementation logic for enumerating IRQ resources
       Return resources
   End Function

   Private Function EnumerateDrivers() As IList(Of DeviceDriver)
       Dim drivers As New List(Of DeviceDriver)()
       ' Implementation logic for enumerating drivers
       Return drivers
   End Function

   ' Example property with refactored getter logic
   Public ReadOnly Property FriendlyName() As String
       Get
           Dim name = GetRegistryProperty(Of String)(DevicePropertyID.FriendlyName, RegistryValueKind.String)
           Return If(name, GetRegistryProperty(Of String)(DevicePropertyID.Description, RegistryValueKind.String))
       End Get
   End Property

   ' Other properties and methods omitted for brevity

   Protected Overrides Sub Finalize()
       Try
           NativeMethods.SetupDiDestroyDeviceInfoList(_deviceInfoset)
       Finally
           MyBase.Finalize()
       End Try
   End Sub
End Class
2 Spice ups

As I’m not much of a VB.NET person, I went based on what I figured may be helpful.
C# would be a bit different however the key differences being that ' --- CONSOLIDATED RESOURCE ENUMERATION --- section.

Hope this helps, or at least sparks something for you.
Added thread safety stuff cause UI may lock up when pulling resources.
So this way you can use threads efficiently

Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Windows.Forms
Imports Microsoft.Win32
Imports System.Threading

Public NotInheritable Class Device

    Private ReadOnly _deviceInfoset As IntPtr
    Private ReadOnly _deviceInfoData As DeviceInstanceInfo
    Private ReadOnly _properties As New Dictionary(Of DevicePropertyID, Object)()
    Private ReadOnly _propertiesLock As New ReaderWriterLockSlim()
    Private ReadOnly _drivers As Lazy(Of IList(Of DeviceDriver))

    ' Unified resource cache
    Private ReadOnly _resourceCache As New Dictionary(Of Type, Object)()
    Private ReadOnly _resourceCacheLock As New ReaderWriterLockSlim()

    Private _flags As DeviceInstanceFlags
    Private _problem As DeviceInstanceProblem

    Public Sub New(hInfoSet As IntPtr, instanceInfo As DeviceInstanceInfo)
        _deviceInfoset = hInfoSet
        _deviceInfoData = instanceInfo
        _drivers = New Lazy(Of IList(Of DeviceDriver))(AddressOf EnumerateDrivers)
        InitializeDeviceStatus()
    End Sub

    Private Sub InitializeDeviceStatus()
        Try
            If NativeMethods.CM_Get_DevNode_Status(_flags, _problem, _deviceInfoData.InstanceID, 0) = ConfigResult.Success Then
                If (_flags And DeviceInstanceFlags.HAS_PROBLEM) = 0 Then
                    _problem = DeviceInstanceProblem.NO_PROBLEM
                End If
            Else
                _flags = DeviceInstanceFlags.HAS_PROBLEM
                _problem = DeviceInstanceProblem.NO_PROBLEM
            End If
        Catch ex As Exception
            Throw New InvalidOperationException("Failed to initialize device status.", ex)
        End Try
    End Sub

    ' --- CONSOLIDATED RESOURCE ENUMERATION ---
    Private Function GetResourceList(Of T)() As IList(Of T)
        _resourceCacheLock.EnterUpgradeableReadLock()
        Try
            If _resourceCache.ContainsKey(GetType(T)) Then
                Return DirectCast(_resourceCache(GetType(T)), IList(Of T))
            End If
            _resourceCacheLock.EnterWriteLock()
            Try
                Dim list As IList(Of T)
                If GetType(T) Is GetType(DeviceMemoryRange) Then
                    list = DirectCast(EnumerateMemoryResources(), IList(Of T))
                ElseIf GetType(T) Is GetType(DevicePortRange) Then
                    list = DirectCast(EnumeratePortResources(), IList(Of T))
                ElseIf GetType(T) Is GetType(DeviceDMARange) Then
                    list = DirectCast(EnumerateDMAResources(), IList(Of T))
                ElseIf GetType(T) Is GetType(DeviceIRQRange) Then
                    list = DirectCast(EnumerateIRQResources(), IList(Of T))
                Else
                    Throw New NotSupportedException($"Resource type {GetType(T).Name} not supported.")
                End If
                _resourceCache(GetType(T)) = list
                Return list
            Finally
                _resourceCacheLock.ExitWriteLock()
            End Try
        Finally
            _resourceCacheLock.ExitUpgradeableReadLock()
        End Try
    End Function

    ' --- RESOURCE ENUMERATION METHODS ---
    Private Function EnumerateMemoryResources() As IList(Of DeviceMemoryRange)
        Dim resources As New List(Of DeviceMemoryRange)()
        ' Example: Call your NativeMethods here
        ' NativeMethods.EnumerateMemoryResources(_deviceInfoset, _deviceInfoData, resources)
        Return resources
    End Function

    Private Function EnumeratePortResources() As IList(Of DevicePortRange)
        Dim resources As New List(Of DevicePortRange)()
        ' Example: Call your NativeMethods here
        ' NativeMethods.EnumeratePortResources(_deviceInfoset, _deviceInfoData, resources)
        Return resources
    End Function

    Private Function EnumerateDMAResources() As IList(Of DeviceDMARange)
        Dim resources As New List(Of DeviceDMARange)()
        ' Example: Call your NativeMethods here
        ' NativeMethods.EnumerateDMAResources(_deviceInfoset, _deviceInfoData, resources)
        Return resources
    End Function

    Private Function EnumerateIRQResources() As IList(Of DeviceIRQRange)
        Dim resources As New List(Of DeviceIRQRange)()
        ' Example: Call your NativeMethods here
        ' NativeMethods.EnumerateIRQResources(_deviceInfoset, _deviceInfoData, resources)
        Return resources
    End Function

    Private Function EnumerateDrivers() As IList(Of DeviceDriver)
        Dim drivers As New List(Of DeviceDriver)()
        ' Example: Call your NativeMethods here
        ' NativeMethods.EnumerateDrivers(_deviceInfoset, _deviceInfoData, drivers)
        Return drivers
    End Function

    ' --- TYPE-SAFE, THREAD-SAFE REGISTRY PROPERTY ACCESS WITH ERROR HANDLING ---
    Private Function GetRegistryProperty(Of T)(propertyID As DevicePropertyID, expectedType As RegistryValueKind) As T
        _propertiesLock.EnterUpgradeableReadLock()
        Try
            If _properties.ContainsKey(propertyID) Then
                Return DirectCast(_properties(propertyID), T)
            End If

            _propertiesLock.EnterWriteLock()
            Try
                Dim buffer(1023) As Byte
                Dim requiredSize As Integer
                Dim dataType As RegistryValueKind

                If Not NativeMethods.SetupDiGetDeviceRegistryPropertyW(_deviceInfoset, _deviceInfoData, propertyID, dataType, buffer, buffer.Length, requiredSize) Then
                    Throw New InvalidOperationException($"Failed to retrieve property {propertyID}.")
                End If

                If dataType <> expectedType Then
                    Throw New InvalidCastException($"Unexpected registry value type: {dataType} (expected {expectedType})")
                End If

                Dim value As Object = ConvertRegistryBuffer(buffer, requiredSize, dataType, GetType(T))
                _properties(propertyID) = value
                Return DirectCast(value, T)
            Finally
                _propertiesLock.ExitWriteLock()
            End Try
        Finally
            _propertiesLock.ExitUpgradeableReadLock()
        End Try
    End Function

    ' --- TYPE CONVERSION LOGIC ---
    Private Shared Function ConvertRegistryBuffer(buffer As Byte(), size As Integer, kind As RegistryValueKind, targetType As Type) As Object
        Select Case kind
            Case RegistryValueKind.String, RegistryValueKind.ExpandString
                Dim str As String = Encoding.Unicode.GetString(buffer, 0, size)
                Dim nullIdx = str.IndexOf(ChrW(0))
                If nullIdx >= 0 Then str = str.Substring(0, nullIdx)
                Return str
            Case RegistryValueKind.DWord
                If size < 4 Then Throw New InvalidCastException("DWORD registry value too small.")
                Dim val As Integer = BitConverter.ToInt32(buffer, 0)
                If targetType Is GetType(Boolean) Then
                    Return val <> 0
                End If
                Return Convert.ChangeType(val, targetType)
            Case RegistryValueKind.QWord
                If size < 8 Then Throw New InvalidCastException("QWORD registry value too small.")
                Dim val As Long = BitConverter.ToInt64(buffer, 0)
                Return Convert.ChangeType(val, targetType)
            Case RegistryValueKind.MultiString
                Dim str As String = Encoding.Unicode.GetString(buffer, 0, size)
                Return str.Split(New Char() {ChrW(0)}, StringSplitOptions.RemoveEmptyEntries)
            Case RegistryValueKind.Binary
                Dim result(size - 1) As Byte
                Array.Copy(buffer, result, size)
                Return result
            Case Else
                Throw New NotSupportedException($"Registry value kind {kind} is not supported.")
        End Select
    End Function

    ' --- PROPERTIES USING CONSOLIDATED LOGIC ---
    Public ReadOnly Property FriendlyName() As String
        Get
            Try
                Return GetRegistryProperty(Of String)(DevicePropertyID.FriendlyName, RegistryValueKind.String)
            Catch
                Return GetRegistryProperty(Of String)(DevicePropertyID.Description, RegistryValueKind.String)
            End Try
        End Get
    End Property

    Public ReadOnly Property MemoryRanges As IList(Of DeviceMemoryRange)
        Get
            Return GetResourceList(Of DeviceMemoryRange)()
        End Get
    End Property

    Public ReadOnly Property PortRanges As IList(Of DevicePortRange)
        Get
            Return GetResourceList(Of DevicePortRange)()
        End Get
    End Property

    Public ReadOnly Property DMARanges As IList(Of DeviceDMARange)
        Get
            Return GetResourceList(Of DeviceDMARange)()
        End Get
    End Property

    Public ReadOnly Property IRQRanges As IList(Of DeviceIRQRange)
        Get
            Return GetResourceList(Of DeviceIRQRange)()
        End Get
    End Property

    Public ReadOnly Property Drivers As IList(Of DeviceDriver)
        Get
            Return _drivers.Value
        End Get
    End Property

    Protected Overrides Sub Finalize()
        Try
            NativeMethods.SetupDiDestroyDeviceInfoList(_deviceInfoset)
        Finally
            MyBase.Finalize()
        End Try
    End Sub
End Class