views:

71

answers:

3

I have a class which get all the bytes from a file, then it splits up the bytes into three parts (a header, index and body) these 3 parts get passed along to 3 classes (called header, body and index) respectively. When the bytes in the three classes gets modified how can I pass these changes back up to the first class (the one that got the bytes from a file).
Must I have a property in each of the head, index and body classes called parentclass and then set the property when the classes are created?
This could get chaotic when the 3 classes are split up further.

A file is loaded and the bytes put into a property called data() then the bytes are split at certian places/offsets into three parts. One part gets put into a property called data() in a class called header the other two part are also put into properties called data but in another two classes called body and index.  The user, through the form ui, modifies the data in the 3 classes (header, index and body) I want this data to be passed back to the first class combined and then it can be saved as a file. 

Or I just want to be able to referenc the data.  

A: 

What else do those classes do? If their entire purpose is to modify these bytes, then why not put them in a method and return the modifications?

Depending on what you're code looks like, you may also benefit from using events.

A: 

Even though you describe a "parent class", it doesn't sound like you're truly using a class hierarchy. I would make use of a separate abstract class and polymorphism to achieve what it sounds like you want to do. For example:

  • Create a MyFile class that represents your file, and has properties Header, Body, Index, etc. MyFile should implement IDisposable and have a Close method for closing the file; opening the file can be handled by a constructor that takes a file name.

  • Create an abstract class (in VB.NET I believe the keyword is MustInherit) called FilePart that has a protected readonly member parentFile which is a reference to a MyFile object. FilePart should have a single protected constructor which takes a MyFile object and populates the file member -- then classes that inherit from FilePart must be associated with a MyFile instance.

  • Create subclasses that inherit from FilePart called MyFileHeader, MyFileIndex, MyFileBody, etc. Each should have an internal (in VB.NET I think this called Friend) constructor that takes a MyFile and a byte array.

  • When you open a MyFile, the constructor (or an Open method, if you prefer) can parse the file and split it up into byte arrays. Then it can create new objects for each file part, e.g. with Me.Header = New MyFileHeader(Me, headerBytes). Other code can interact with the file parts directly, modifying data as needed.

  • Each FilePart can have a method called GetBytes that returns the bytes corresponding to its current state. MyFile can have a method Save that can call, for example, outputFile.WriteBytes(Me.Header.GetBytes()) etc.

If you need to split the file up further, just have MyFile contain an IList(Of FilePart) called FileParts or something like that. Then you can fill it with whatever file parts you like, and since they are all subclasses of FilePart, the MyFile code can interact with them the same way.

Daniel Pryden
in the second bullet point you say to make a read only member called `parentFile` and then to set a member called `file` you haven't mentioned `file` before and if you mean `parentFile` then it is read only so it can not be set.
Jonathan
@Jonathan: My bad, I meant `parentFile` there. If you declare the member as a `ReadOnly` variable, it can still be set by the constructor, just not changed to a different variable once it's been set. See the section on "ReadOnly variable" on this page: http://msdn.microsoft.com/en-us/library/z2b2c2ka.aspx?ppud=4 ; also, the C# documentation for `readonly` does a good job explaining how it can be used: http://msdn.microsoft.com/en-us/library/acdd6hb7.aspx
Daniel Pryden
+1  A: 

Concept

Really it's about code design. E.g. whether to use inheritance, composition, or both. The answer will also depend on the peripherals of what you're trying to do (e.g. the code we don't see in your question).

Here's just one set of ideas about allowing your parts to reintegrate themselves to a parent context after their bytes are changed.

E.g. Require the "parent" instance (I'll call it "context" in my example) to be passed to Header, Footer and Body when they are constructed; they can always contact the parent back at anytime to reassemble, access context members, or vice-versa. It's kind of like the Value property you mentioned but makes it immutable after construction.

alt text

Sample Implementation

We'll make BytesContext read from the file and be responsible for splitting the bytes into other classes.

For example, Dim c as New BytesContext() and c.ParseAllBytes() method is called as follows:

Class BytesContext

    Sub ParseAllBytes()

        'READ ALL BYTES FROM FILE

        'INSTANTIATE PARTS

        ' Each part takes a reference to this context.
        Dim header As New HeaderBytes(Me)
        header.Data = someOfTheParsedBytes

        Dim body As New BodyBytes(Me, MaybeSomeBytesHere[])

        Dim footer As New FooterBytes(Me)
        ..etc.

        ' Can always know the context.
        Console.Write("Body context is " & body.Context.ToString())

    End Sub

    ' A method that puts the pieces back together.
    '
    Sub PutBackTogether(part As BasePart)
         If Typeof(part) Is HeaderBytes ...
         ...
         ElseIf Typeof(part) Is FooterBytes...
         ... etc.
    End Sub

End Class

HeaderBytes (and the other kinds of parts) take a reference to the context as an instantiation argument - they all pass it to a base class for safe keeping (see next snippet):

Class HeaderBytes
    Inherits BasePart

    Sub New(ByVal context As BytesContext)
        MyBase.New(context) 'Store in base class.
    End Sub

    ''' REASSEMBLE SELF BACK INTO ORIGINAL
    ''' This instance can reference it's context and reintegrate its changes
    Sub Save()
        Context.PutBackTogether(Me)
    End Sub

End Class

Class FooterBytes
    Inherits BasePart
'...same...

Class BodyBytes
    Inherits BasePart
'...same...

Note: the above part has the ability to reintegrate its changes into the original context.

This is the base part to share logic between parts, and keep a reference to the context for parts:

 Class BasePart

    '''Remember context.
    Private _context As BytesContext

    Public Sub New(ByVal context As BytesContext)
        If _context Is Nothing Then Throw New ArgumentNullException("context")
        _context = context
    End Sub

    ''' Getter allows access to context.
    ReadOnly Property Context() As BytesContext
        Get
            Return _context
        End Get
    End Property

End Class
John K
why does the context in HeaderBytes have to be passed to a base class, why can't it just be stored in the HeaderBytes class itself?
Jonathan
It can be stored in either place. The base class is just a personal preference of mine because it consolidates the context referencing source code in one class instead of putting the same code in three classes (Header, Body and Footer).
John K