Reputation: 2498
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
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
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
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