How to copy an object before an edit, and then replace the edited object if needed

905 Views Asked by At

I am coding a C# WinForms application where I have a form to edit objects. The form has a function setObject() that sets an object to a private field and a function getObject() to get the object. I am calling this function before the form's shown dialog is called.

After the form is shown, the values of the object can be edited. Such as items in a Collection<T> can be modified.

If a user presses a cancel button, I do not want the changes to persist for the object.

How is the best way to code this? Should I copy the object before the form is shown, and if the cancel button is pressed, replace the copied object in place of the edited form object?

I am thinking of a situation where I want to edit an object that is in a collection. After editing the object on the form, the user presses the cancel button. The copied object is then needed to be inserted back into the collection in place of the edited object. As the object being inserted is now a copied object, will there be a problem with reference checks against the old object?

Here is some code to illustrate:

public class Simple1
{
    public Collection<Simple2> simple2Collecton { get; set; }
}

public void simpleFunction()
{
    Simple2 obj = simple2Collecton.First();
    bool value = (obj == simple2Collecton.First());
}

If I have a Simple2 object that references the first item in the simple2Collecton, and I copy the Simple1 object after interacting with the edit form. Will the following code still == true:

bool value = (obj == simple2Collecton.First());

Here is my current code to copy/clone an object:

public static T Clone<T>(this object objSource)
{
    if (!typeof(T).IsSerializable)
    {
        throw new ArgumentException("The type must be serializable.", "source");
    }

    if (Object.ReferenceEquals(objSource, null))
    {
        return default(T);
    }
    using (MemoryStream stream = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(stream, objSource);
        stream.Position = 0;
        return (T)formatter.Deserialize(stream);
    }
}
2

There are 2 best solutions below

1
On

I would suggest that every time your form opens you save a "main instance" (for editing) and a private"fixed instance" of your object as a reference to how it was before editing it. After that I would use reflection to copy the fixed instance into a new main instance and bind it to the form. In your GetObject() method you should always return the main instance and switch between them if the user presses cancel.

0
On

Here is the approach I used for this purpose;

setData(Object)
{
//set object's values to form controls
}

OnEditBtn_Click(Sender,EventArgs)
{
//Iterate over your list and find the object by ID and call setData with 
//searched object
//setData(SearchedObjectToEdit); //It will set form controls with the object data
}
Cancel_Button_Click(Sender,EventArgs)
{
//create a new tempObj, instance of the object.
//call setData(tempObj), it will set the blank values to form controls,
//showing that changes has been reverted
}

OnSubmitBtn_Click(Sender, EventArgs)
{
 //iterate over your collection and replace the edited object when ID is found
}

As per your object copying part, object copying will be an issue as they are reference-type and they will not be exchanged until exactly same reference is not found.

Why not discard the changes on cancelBtnClick rather than saving them. It won't effect the original object in Collection.