Hi!
In case you are going to use anything from our patch...
Me and my colleague have been discussing the effect of the override of the Entity.Equals method (Actually, it was my colleague that realized the effect first - not me :-)). And there is a small issue with our patch that should probably be addressed in the final fix;
The correct implementation of a clone method is to make it return a complete copy / clone of the source tree - exact. This is what the patch actually did until the Entity.Equal method was overridden. We just didn't see the consequences of the method being overridden, first. I'll try to explain:
Let's say the source tree we are about to clone, somehow would contain two instances of the same type (for instance the Person type):
obj1 : Person
/
objx
\
ob2 : Person
...and those two Person objects contained the same values - making them equal except for the references from objx. The only thing that do differentiate those two objects are the references. With the patch above, calling clone() on objx will now produce a copy looking like this:
objxCopy = obj1Copy : Person
where objxCopy will contain two references to same person object. (The equal sign (=) now represents two distinct references, both pointing to the same object). The reason for this is:
-When the clone logic checks if an object has been copied before, it calls Contains(objext y) on its dictionary of sourceobjects already copied (Check the line 59 in the patch file for an example of the contains method being used.). The dictionary then calls the Equals() method on each of the items in the dictionary to find whether the source object actually exists as a key in the dictionary. The new implementation of the Entity.Equals() method evaluates the actual values of the object, and returns true if the values are equal - while the old one only evaluated the object references. Due to this change in the Equals method, the same copy will be used for both the references in the target tree. In our case we want to evaluate the object references, not the values in the object.
The clone implementation must always return a exact copy of the source which is not the case after the Entity.Equals() is overridden. And we can't just change the Entity.Equals() method of course. So the best solution we could come up width, was to create our own implementation of the dictionary used for holding the existing copies, by extending the Hashtable class, for instance. Then provide a new implementation of the Contains() method, and make it to use the Object.ReferenceEquals(object a, object b) instead of using the entity.Equals(object x) during its search for a match.
Hope this was understandable.
-Jan Ivar