Open mrinalkamboj opened 6 years ago
There is no public api to do this. But if you want to override current implementation, you can see to DeepClonerSafeTypes class, there are two corresponding methods:
You can override implementation of both methods (by the request, CanNotDeepCopyClass looks more appropriate) to reduce deep copying of object.
Thanks, I exposed a Helper class with method to add a specific Type like ServiceProduct
to KnownTypes
dictionary for shallow cloning and it does work as expected, however in this case I still cannot have object level control, since whole type will always be Shallow cloned, is there a way to make it object level control, where specific objects are only shallow cloned, not a given Type. this would be fine grain control. I was trying to figure out in code where does it consider the object hierarchy for cloning the aggregations and compositions, but was unsure. Can you please provide more information.
It seems, there are no good ability to do that. Current implementation do object cloning recursively but each object is independent and use same code for cloning. You can look at DeepClonerGenerator, CloneClassRoot method to determine initial object and CloneClassInternal for cloning dependent objects. DeepCloneState can be used for some meta info.
One issue with deep cloning is that HashSets of objects whose hash codes are generated by reference (the default) will be copied with the persisted hash codes representing the original objects, not the newly cloned ones (likewise for Dictionaries). This can cause unexpected behaviour, e.g. HashSet.Contains will return false when it actually does contain the provided object.
This does limit the usefulness of blindly cloning a deep, complex object structure. It would be nice if there was a way to specify object types that we don't want to deep clone via reflection and potentially could provide delegates to perform the clone for these types instead.
e.g.
myObject.DeepClone(
new Dictionary<Type, Func<object, object>>
{
{ typeof(HashSet<>), hashSet => "do something smart" }
}
);
As per mrinalkamboj's use case, this could be per object rather than per type.
Alternatively, the framework could just treat HashSets & Dictionaries (and any other Hash based collections) as special cases: e.g. emit a constructor for the relevant generic type and then iterate through the collection calling Add for each cloned element. This would be preferable for my use case, and should still be super fast
Thanks. It is interesting issue. It is bad idea to store objects without GetHashCode
implementation due undefined behavior for such operations, but it possible, so, some solution should be provided by DeepCloner.
I'll think about better solution to do this, because simple specific method for HashSets and Dictionaries can be problematic due lot of types of such collections and ability to specify there custom equality comparers. Custom options for cloning types/objects can be useful. I'll think about best solution to do this.
Did this issue with cloning HashSet (containing objects without GetHashCode implementation) get solved ?
No. Sorry.
Is there a provision in the library to make shallow copy of few expensive objects, while we deep copy the remaining object graph. I doubt on reviewing the APIs, I do plan to make code change, by supplying an explicit Dictionary with expensive objects added to it and in case object is there in the dictionary then create a Shallow version else a regular code which creates a deep version. Please suggest if my understanding is correct and may be some guidance to make code modification.
To provide more clarity:
My object is of following type, where both ODPair and ServiceProduct are the custom types. ServiceProduct is an expensive object, for which I want to retain the Shallow copy, while rest of the object is deep copied
Dictionary<ODPair,Dictionary<string,List<ServiceProduct>>>