lilactiger89
lilactiger89

Reputation: 2498

Find object of given Type

I'm in an odd situation. I have a horrendous number of classes that derive from each other and I store objects in various collections.

So for example:

Record <-- CostRecord <-- AccruedCostRecord
                      <-- PrepaidCostRecord
                      <-- StockRecord

The objects are stored in a List(Of Record) and I want to search a particular list for a record of a given type.

    Private Function findRecord(listToSearch As List(of Record), recordName As String, recordType As Type) As Record
        For i As Integer = 0 To listToSearch.Count - 1
            If listToSearch(i).name.equals(recordName)
                'If record is of type "recordType" then return it
            End If
        Next
    End Function

Normally I would use the "TypeOf ... Is" operator as I am interested in the base class types too. So if I passed in "CostRecord" I would expect to retrieve a AccruedCostRecord, PrepaidCostRecord or StockRecord.

In this case I can't use TypeOf because it doesn't accept System.Type as an argument and I can't think of another way of telling it what I want.

I don't believe that "GetType" is going to help me here either because I'm interested in base classes.

Has anyone any ideas? Perhaps some kind of crazy Reflection magic?

Thanks

Upvotes: 2

Views: 82

Answers (3)

Adriano Repetti
Adriano Repetti

Reputation: 67080

I would rewrite it with LINQ but as quick answer you may do this:

Private Function findRecord(listToSearch As List(of Record), recordName As String, recordType As Type) As Record
    For i As Integer = 0 To listToSearch.Count - 1
        If listToSearch(i).name.equals(recordName) And listToSearch(i).GetType() = recordType Then
            ' ...
        End If
    Next
End Function

Key point is this comparison: listToSearch(i).GetType() = recordType, GetType() method (inherited from Object) will return object type as Type (then comparable with your parameter). With strict comparison it'll match only objects exactly of given type (then if you specify PrepaidCostRecord for recordType it'll match only that and if you specify CostRecord then it won't match anything).

To include derived classes (so you can specify, for example, CostRecord for your parameter recordType and it'll match all derived classes like PrepaidCostRecord but not ancestors like Record) you just have to change it to:

recordType.IsAssignableFrom(listToSearch(i).GetType())

Final code will then be:

Private Function findRecord(listToSearch As List(of Record), recordName As String, recordType As Type) As Record
    For i As Integer = 0 To listToSearch.Count - 1
        If listToSearch(i).name.equals(recordName) And recordType.IsAssignableFrom(listToSearch(i).GetType()) Then
            ' ...
        End If
    Next
End Function

Now it's time to rewrite it with LINQ, for example:

Dim records = From record In listToSearch_
    Where record.name.equals(recordName) And recordType.IsAssignableFrom(record.GetType)

In your case you can rewrite it shorter as:

Private Function findRecord(listToSearch As List(of Record), recordName As String, recordType As Type) As Record
    findRecord = listToSearch.FirstOrDefault(Function(r) r.name.equals(recordName) And recordType.IsAssignableFrom(r.GetType))
End Function

Upvotes: 1

ThorstenC
ThorstenC

Reputation: 1314

you can use GetType.BaseType to see if the base type is the class you are looking for. If not you can go deeper in Gettype.Baseytpe.BaseType.

Upvotes: -1

Dan Puzey
Dan Puzey

Reputation: 34200

You can use the method .IsAssignableFrom on your type:

If recordType.IsAssignableFrom(listToSearch(i).GetType())

For example, if your list item is AccruedCostRecord and your recordType is CostRecord, this will return True.

Upvotes: 1

Related Questions