Search code examples
vb.netcompact-framework

vb.net class upcasting / downcasting


I'm having an issue with casting classes in vb.net, I'm using Visual Studio 2008 with the Compact Framework 3.5 as I'm working on legacy Windows Mobile project.

I have a DLL which acts as the Data Layer for accessing Database objects in SqlCe and I cant change any of the code in there, however I want to add extra functionality to the exposed classes for the Business logic so I created my own classes and Inherited the classes from the Data Layer

Public Partial Class Customers
    Public Function ListAll() As IEnumerable(Of Customers)
        'Do Work
    End Function
End Class

Public Class MyCustomers
    Inherits Customers

    Public Function FindCustomer(ID As Integer)
    End Function
End Class

so in my code I would write something like

For Each c As MyCustomer In Customers.ListAll
    'I want to be able to use my c.FindCustomer(), but I get an InvalidCast Exception above.
Next

I get that this is an issue with upcasting / downcasting (I don't remember which way is which), but how can I solve it ?

I can't change the return type of Customers.ListAll() but I need to be able to add methods and properties to implement the business logic.


Solution

  • Inside the For Each loop:

    For a one-shot:

    DirectCast(c, MyCustomer).FindCustomer(1) 'for id 1
    

    To use more than one time:

    Dim customer as MyCustomer = DirectCast(c, MyCustomer)
    customer.FindCustomer(1)
    

    You can also do:

    With DirectCast(c, MyCustomer)
        .FindCustomer(1)
        .AnotherMethod()
        'etc
    End With
    

    Have fun!


    Here's an alternative. I'm not sure of the exact architecture of your project, so I'll assume it's like this:

    Customers      -has a list of Customer
    MyCustomers    -child of Customers with a list of MyCustomer and more functionalities
    
    Customer       -base entry
    MyCustomer     -base entry with more functionalities
    

    The problem being that you cannot cast an object into it's child (this sort of operation can only work in the other direction), this is basically an impossible problem. Yet you can bypass it with some cloning. This tells me that the base data is the same for Customer and MyCustomer, you only added more methods. Which is great, because it also means that you can manually transform a Customer into a MyCustomer. You just need it to happen automatically.

    In the MyCustomers and MyCustomer class, you can add theses:

    'In MyCustomers
    Public Shared Function GetMyCustomersFromCustomers(customers As Customers) As MyCustomers
        Dim data As New MyCustomers()
        'copy each modal variable
    
        'create a list of MyCustomer from existing Customer list
        For Each c As Customer In customers.listOfCustomers
                data.listOfMyCustomers.Add(MyCustomer.GetMyCustomerFromCustomer(c))
        Next
    
        Return data
    End Function
    
    'In MyCustomer
    Public Shared Function GetMyCustomerFromCustomer(customer As Customer) As MyCustomer
        Dim data As New MyCustomer
    
        'copy all the data
    
        Return data
    End Function
    

    Then if you want to work with your own objects you can extrapolate them from the ones of the dll:

    'let's say you currently have a 'customers' as Customers object
    Dim myStuff as MyCustomers = MyCustomers.GetMyCustomersFromCustomers(customers)
    

    If you often need the MyCustomers list and don't care about the rest of the class, you can create a Shared function which gives you only the extrapolated list of MyCustomer, no problem.

    This works only as long as you can extrapolate MyCustomer from Customers and MyCustomer from Customer, of course.

    Hope it helps.