0

My application (VSTO/C#) handles excel files editing some cells and inserting some rows.
My problem is more generlaized than this though, and is about defensive coding the class that acts as edtior.

The design is based on a wrapper object for the worksheet, let's call it SheetTable; it contains the fixed data like the positions of the columns and so on.
When I want to change data in my sheet I use another wrapper object, a TableRange that has a property of SheetTable and so knows the table structure inside the sheet.
This is the editor object i was talking about.

When it writes down to the worksheet it handles with particular care operations like inserting rows and deleting rows, because they can invalidate some fix references that the application may hold.
If there are multiple TableRange object, they can mess-up with such references. That's why I'm looking for a well established pattern for allowing at most one instance of TableRange per TableSheet at a time.
The problem per-se is easy, but i'm interested in some details.

The reason why TableRange is not implemented as a part of TableSheet (the 1-1 relation would suggest so) is that I want to be able of throwing away the state of TableRange in the case of canceled updates without affecting the state of TableSheet. So, if the reference of the single TableRange is held by the TableSheet, I need an explicit way of get rid of it. Something like the following

public class TableSheet {

    private TableRange editingRange;

    public TableSheet EditingRange {
        get 
        {
    
            if (editingRange==null) {
                editingRange = new TableRange(this);
            } 
         return editingRange;
         }
    }

    public void CancelEdit() {
        editingRange = null;
    }    
}

Here, the TableRange is lazy initialized when accessing the EditingRange property. This is to reduce the number of states of the object from a client perspective.

I could get rid of the TableRange instance the very same way via a setter and assigning null.

public TableSheet EditingRange {
   get {...}
   set editingRange = value;
}

This would allow the user to assign null. But it would allow the user to assign also another TableRange instance (provided that she can create one, that shouldn't be the case since the constructor should be internal).
Not only that, but if the need of adding deinitialization code should arise, I wouldn't have a place to put it and I should redesign the API. That why I come up with the CancelEdit() method.

So these are my basic ideas on this pattern. what do you think? Do they address the main concerns of this problem? Would you change something? Is there a well-established design pattern for such a problem?

1 Answer 1

3

You could consider the process of updating the spreadsheet similar to a database transaction. ADO.NET and DataSet/DataRow used to have the concept of BeginEdit(), AcceptChanges(), and EndEdit().

BeginEdit()
... do changes...
AcceptChanges()
... changes applied

Or

BeginEdit()
... do changes...
CancelEdit()
... changes rolled back

The code in your example

if (editingRange==null) {
    editingRange = new TableRange(this);
}

Would be part of the BeginEdit() method.

If you want to only have one instance of an object internal to a class then that class needs to fully manage the object's life cycle. So, what is the life cycle of that internal class, when does it get created, when can it change, when can it's values change, when is it destroyed, when is it recreated?

Hope that is somewhat helpful. Happy coding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.