Creating a Custom Enumerator in a Base Class

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Charles Law

    Creating a Custom Enumerator in a Base Class

    I have a base class MyBaseClass, and several classes that inherit from it:
    MyClass1, MyClass2, etc.

    The base class implements IEnumerable(Of IMyBaseClassRow ). The base class
    has a DataTable object that contains different data depending on which of
    MyClass1, MyClass2 are instantiated.

    I want to be able to iterate through the rows of the data table using For
    Each on my derived classes retrieving a custom row with properties specific
    to that child class. I found this article



    which alludes to the technique, but doesn't go all the way to showing how to
    derive custom row classes with the properties. I am also doing this in VB,
    so I don't have Yield Return. Therefore, I am having to code this all by
    hand.

    I want all the enumeration stuff in the base class, so that I don't have to
    reproduce it in every derived class, but I have one stumbling block. This is
    my implementation of Current() in my base class:

    Private ReadOnly Property Current() As IMyBaseClassRow Implements
    System.Collecti ons.Generic.IEn umerator(Of IMyBaseClassRow ).Current
    Get
    If m_CurrentRow = -1 Or m_CurrentRow >
    m_MyBaseClass.D ataTable.Rows.C ount - 1 Then
    Throw New InvalidOperatio nException
    End If

    Return New
    MyBaseClassRow( m_MyBaseClass.D ataTable.Rows(m _CurrentRow))
    End Get
    End Property

    The problem is that this can only return a new MyBaseClassRow, and not a
    MyClass1Row. Therefore, when I do

    For Each row As MyClass1Row in MyClass1Instanc e
    ...
    Next

    the compiler is happy, but it fails at runtime with an InvalidCastExce ption
    on the For Each line.

    I think I need to override something in my MyClass1 or MyClass1Row class,
    but I'm not sure what exactly, or how.

    If this problem makes sense to anyone, please feel free to chip in. Any and
    all help welcome.

    TIA

    Charles


  • Charles Law

    #2
    Re: Creating a Custom Enumerator in a Base Class

    I think I've cracked it.

    In my base class MyBaseClass, I have created a must override function that
    returns an object of the type I want, i.e.

    Protected MustOverride Function GetIMyBaseClass Row(dr As DataRow) As
    IMyBaseClassRow

    In my concrete class, I then override this function:

    Protected Overrides Function GetIMyBaseClass Row(ByVal dr As
    System.Data.Dat aRow) As IMyBaseClassRow
    Return New MyClass1Row(dr)
    End Function

    Finally, Current() in MyBaseClass becomes this:

    Private ReadOnly Property Current() As IMyBaseClassRow Implements
    System.Collecti ons.Generic.IEn umerator(Of IMyBaseClassRow ).Current
    Get
    If m_CurrentRow = -1 Or m_CurrentRow >
    m_MyBaseClass.D ataTable.Rows.C ount - 1 Then
    Throw New InvalidOperatio nException
    End If

    Return
    GetIMyBaseClass Row(m_MyBaseCla ss.DataTable.Ro ws(m_CurrentRow ))
    End Get
    End Property

    It allows the base class to call the derived class to get an object of the
    actual type required.

    I hope this helps someone.

    If anyone has another solution, I am still very interested to hear.

    Charles


    "Charles Law" <blank@nowhere. comwrote in message
    news:OWpQYelGJH A.4408@TK2MSFTN GP04.phx.gbl...
    >I have a base class MyBaseClass, and several classes that inherit from it:
    >MyClass1, MyClass2, etc.
    >
    The base class implements IEnumerable(Of IMyBaseClassRow ). The base class
    has a DataTable object that contains different data depending on which of
    MyClass1, MyClass2 are instantiated.
    >
    I want to be able to iterate through the rows of the data table using For
    Each on my derived classes retrieving a custom row with properties
    specific to that child class. I found this article
    >

    >
    which alludes to the technique, but doesn't go all the way to showing how
    to derive custom row classes with the properties. I am also doing this in
    VB, so I don't have Yield Return. Therefore, I am having to code this all
    by hand.
    >
    I want all the enumeration stuff in the base class, so that I don't have
    to reproduce it in every derived class, but I have one stumbling block.
    This is my implementation of Current() in my base class:
    >
    Private ReadOnly Property Current() As IMyBaseClassRow Implements
    System.Collecti ons.Generic.IEn umerator(Of IMyBaseClassRow ).Current
    Get
    If m_CurrentRow = -1 Or m_CurrentRow >
    m_MyBaseClass.D ataTable.Rows.C ount - 1 Then
    Throw New InvalidOperatio nException
    End If
    >
    Return New
    MyBaseClassRow( m_MyBaseClass.D ataTable.Rows(m _CurrentRow))
    End Get
    End Property
    >
    The problem is that this can only return a new MyBaseClassRow, and not a
    MyClass1Row. Therefore, when I do
    >
    For Each row As MyClass1Row in MyClass1Instanc e
    ...
    Next
    >
    the compiler is happy, but it fails at runtime with an
    InvalidCastExce ption on the For Each line.
    >
    I think I need to override something in my MyClass1 or MyClass1Row class,
    but I'm not sure what exactly, or how.
    >
    If this problem makes sense to anyone, please feel free to chip in. Any
    and all help welcome.
    >
    TIA
    >
    Charles
    >
    >

    Comment

    Working...