How to make a "clean" copy of a BO?

How to make a "clean" copy of a BO?

Old forum URL: forums.lhotka.net/forums/t/159.aspx


Dawn posted on Sunday, May 21, 2006

I have hierachical BO like this:

Root
  ChildList->Child
        GrandChildList->GrandChild

I want all the BusinessBase<T> object copyable, in this scenaio Root, ChildList, Child, GrandGhildList,GrandChild.

When user edit the Root object in UI, she can create a Child(First), then she can do a copy command copy the Frist Child, adding to the Child List. Now can't just do a Clone of child, should manually change the identity of the second child, namely let the Second Child GetIDValue() return different value with first Child. And Here is my solution, every BO in this project implements a ICopyable<T> interface which just a one method T Copy(), the implemention in this method like this:

1. for Root Object, Call Clone first, then change the property I need, then call it ChildList.Copy method.

public Root Copy()
{
    Root temp = this.Clone();

    temp.Code = GetNewCode();
   
    temp.childList = this.childList.Copy();

    temp.MarkNew();

    return temp;
}

2. for ChildListObject

public ChildList Copy()
{
    ChildList tempList = ChidlList.NewChildList();

    foreach(Child child in this)
    {
        tempList.add(child.Copy())
    }
   
    return tempList;

}

3. for Child

public Child Copy()
{
    Child temp = Child.Clone();

    temp.ID = NewIDValue();

    temp.grandChildList = this.grandChildList.Copy();
   
    temp.MarkNew();   

    return temp;
}

the GrandChildList and GrandChild work just like ChildList and Child.

It's seem should be work, but when I bind Object to UI, some problem occur. Actually the copy intention is just get a new BO with almost same content with the old one, namely the BO generated by copy should be "Clean", "Clean" means the _stateStack in BusinessBase<T> should clean, the EditLevel should be at zero, but once you bind to UI control, it's semm the binding stuff called IEditableObject.BeginEdit(), which make the _stateStack and EditLevel "unClean", at this time, when I do child copy(), and add it to the childList, the Root's CancelEdit() doent's work properly, if I Call CancelEdit() of Root, it's should remove the copyed child from the childList, but it doesn't.

I think the problem(not sure) is the copyed child _stateStack and EditLevel is not "Clean". beacuse when I Fetch a BO from Database, In all the hierachical of the BO, the _stateStack and EditLevel is "Clean", then I do any copy stuff, it's work, it's just like add a new child BO. So my question here:

How Can I do a "Clean" Copy ?

this is my solution now:

In the Copy Method, I use Relection to get the EditLevel of the BO, beacuse it's hide to drived class, if it not equal to Zero, I'll call ApplyEdit() EditLevel times, means munally clean it's stack and editLevel.

public Child Copy()
{

    Child temp = Child.Clone();
   
    Hack.CleanBOStack(temp); // Here check the editLevel, and clean it's stack

    temp.ID = NewIDValue();

    temp.grandChildList = this.grandChildList.Copy();
   
    temp.MarkNew();   

    return temp;


}

Is this correct way to do this, any ideas?

Sorry for my poor english.

Dawn

Yes "Software is too darn Hard"



RockfordLhotka replied on Sunday, May 21, 2006

The implementation of the Clone() method is discussed in the book - and of course it uses the BinaryFormatter, so it copies the object graph's entire state.

If you want to copy an object graph that is in the process of being edited, but you want the copy to have edit level 0, then you must either set the original object's edit level to 0, or set the copy's level to 0 as you suggest.

I would point out that the EditLevel property is protected in scope, so you don't need to use reflection. It is merely marked with an attribute so Intellisense doesn't show it - but that doesn't prevent you from calling it. The exception here is BusinessListBase, which doesn't expose the property (yet - I'm adding that to 2.0.1).

So in general, I think your plan to call ApplyEdit() until the edit level is 0 is an appropriate way to go.

internal void InitializeCopy(int newId)
{
  while (EditLevel > 0)
    ApplyEdit(0);
  _id = newId;
}

 

Dawn replied on Monday, May 22, 2006

Thanks Rocky.

Yes, VS Intellisense Hide the property. I wonder is this a good way to copy,
or should I manually define a private copy constuctor, copy everty property manually?

RockfordLhotka replied on Tuesday, May 23, 2006

The Clone() concept copies not only the object, but also the object's child objects. It copies the entire object graph starting with the object you pass in.

If you want to copy an object without its children, you are better off copying either field manually.

Copyright (c) Marimer LLC