Class object property which references another object instance of same object type

Viewed 48

I have a class object which looks like this:

Public Class item
    Public Property ID
    Public Property Name
    Public Property Description
    Public Property Type
    Public Property Alias
End Class

I am currently storing these as a dictionary like this:

Public Class Items

    Public ReadOnly dict Dictionary(Of String, item) From {
        {"A", New item With {.Name = "Object A", .Description = "Object A description"}},
        {"B", New item With {.Name = "Object B", .Description = "Object B description"}},
        {"C", New item With {.Alias = "A"}}
    }

    Public Function GetItem(ByVal ID As String) As item
        Return If(dict.ContainsKey(ID), idct.Item(ID), Nothing)
    End Function

End Class

The complexity is that sometimes an item will not have any properties itself but instead has an .Alias property which says "All of my properties are the same as item with this ID, check that object instead".

How should I write my class object item so that this code returns "Object A":

Dim newItem As item = GetItem("C")
Debug.WriteLine(item.Name)

Object C is an alias of Object A so I should return some properties (not always all of them) for Object A instead of Nothing.

A way around this is by adding the below function to the Items class:

Public Function GetItemDescription(ByVal ID As String) As String
    If dict.ContainsKey(ID) Then
        If dict.Item(ID).Description = "" Then
            Return GetItemDescription(dict.Item(ID).Alias)
        Else
            Return dict.Item(ID).Description
        End If
    Else
        Return ""
    End If
End Function

However this doesn't feel like the correct way as then I have to repeatedly call a set of Items.GetPropertyXYZ functions rather than directly referencing the object (e.g. item.Description would have to be GetItemDescription("C")

Is my solution acceptable from a design persepctive, or is there a better way to achieve this?

2 Answers

Try this:

Public Function GetItem(ByVal [alias] As String) As item
    Return dict.Where(Function(a) a.Key = [alias]).Select(Function(b) b.Value).FirstOrDefault
End Function

Edit 1

Certainly it returns the "C" item because its wrong. Sorry.

This one works (Tested):

Public Function GetItem(ByVal ID As String) As item
    Dim itm As item = dict.Where(Function(a) a.Key = ID).Select(Function(b) b.Value).FirstOrDefault

    Return If(itm IsNot Nothing, If(itm.Alias IsNot Nothing, dict(itm.Alias), itm), Nothing)
End Function

JQSOFT's answer does achieve a similar thing, however I've since realised a more granular way I can achieve the same result.

Private Property _description As String
Public Property Description As String
    Get
        If _Description = "" Then
            If [Alias] IsNot Nothing Then
                Return dict.Item([Alias]).Description
            Else
                Return ""
            End If
        Else
            Return _description 
        End If
    End Get
    Set(value As String)
        _description = value
    End Set
End Property

This way allows me to specify whether I return the data from Object A at property level, rather than returning an entirely different object.

Also, .Alias is a terrible property name as it's also a keyword, I'm going to use .Synonym.

Related