Fixes issue of observable collections, event binding and deep cloning
This commit is contained in:
@@ -438,6 +438,7 @@ namespace Umbraco.Core.Models
|
||||
_contentType = contentType;
|
||||
ContentTypeBase = contentType;
|
||||
Properties.EnsurePropertyTypes(PropertyTypes);
|
||||
//TODO: Shouldn't we remove this event handler first before re-adding it in case the handler already exists
|
||||
Properties.CollectionChanged += PropertiesChanged;
|
||||
}
|
||||
|
||||
@@ -455,6 +456,7 @@ namespace Umbraco.Core.Models
|
||||
_contentType = contentType;
|
||||
ContentTypeBase = contentType;
|
||||
Properties.EnsureCleanPropertyTypes(PropertyTypes);
|
||||
//TODO: Shouldn't we remove this event handler first before re-adding it in case the handler already exists
|
||||
Properties.CollectionChanged += PropertiesChanged;
|
||||
return;
|
||||
}
|
||||
@@ -500,10 +502,18 @@ namespace Umbraco.Core.Models
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (Content) base.DeepClone();
|
||||
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
//need to manually clone this since it's not settable
|
||||
clone._contentType = (IContentType)ContentType.DeepClone();
|
||||
|
||||
//if culture infos exist then deal with event bindings
|
||||
if (clone._publishInfos != null)
|
||||
{
|
||||
clone._publishInfos.CollectionChanged -= this.PublishNamesCollectionChanged; //clear this event handler if any
|
||||
clone._publishInfos = (CultureNameCollection)_publishInfos.DeepClone(); //manually deep clone
|
||||
clone._publishInfos.CollectionChanged += clone.PublishNamesCollectionChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
|
||||
@@ -113,7 +113,11 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Gets or sets the collection of properties for the entity.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Marked DoNotClone since we'll manually clone the underlying field to deal with the event handling
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
[DoNotClone]
|
||||
public virtual PropertyCollection Properties
|
||||
{
|
||||
get => _properties;
|
||||
@@ -477,5 +481,39 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Override to deal with specific object instances
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override object DeepClone()
|
||||
{
|
||||
var clone = (ContentBase)base.DeepClone();
|
||||
//turn off change tracking
|
||||
clone.DisableChangeTracking();
|
||||
|
||||
//if culture infos exist then deal with event bindings
|
||||
if (clone._cultureInfos != null)
|
||||
{
|
||||
clone._cultureInfos.CollectionChanged -= this.CultureNamesCollectionChanged; //clear this event handler if any
|
||||
clone._cultureInfos = (CultureNameCollection)_cultureInfos.DeepClone(); //manually deep clone
|
||||
clone._cultureInfos.CollectionChanged += clone.CultureNamesCollectionChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
//if properties exist then deal with event bindings
|
||||
if (clone._properties != null)
|
||||
{
|
||||
clone._properties.CollectionChanged -= this.PropertiesChanged; //clear this event handler if any
|
||||
clone._properties = (PropertyCollection)_properties.DeepClone(); //manually deep clone
|
||||
clone._properties.CollectionChanged += clone.PropertiesChanged; //re-assign correct event handler
|
||||
}
|
||||
|
||||
//this shouldn't really be needed since we're not tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
//re-enable tracking
|
||||
clone.EnableChangeTracking();
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ namespace Umbraco.Core.Models.Entities
|
||||
[DebuggerDisplay("Id: {" + nameof(Id) + "}")]
|
||||
public abstract class EntityBase : BeingDirtyBase, IEntity
|
||||
{
|
||||
#if DEBUG
|
||||
public Guid InstanceId = Guid.NewGuid();
|
||||
#endif
|
||||
|
||||
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
|
||||
|
||||
private bool _hasIdentity;
|
||||
@@ -161,6 +165,11 @@ namespace Umbraco.Core.Models.Entities
|
||||
var unused = Key; // ensure that 'this' has a key, before cloning
|
||||
var clone = (EntityBase) MemberwiseClone();
|
||||
|
||||
#if DEBUG
|
||||
clone.InstanceId = Guid.NewGuid();
|
||||
#endif
|
||||
|
||||
|
||||
// clear changes (ensures the clone has its own dictionaries)
|
||||
// then disable change tracking
|
||||
clone.ResetDirtyProperties(false);
|
||||
|
||||
Reference in New Issue
Block a user