diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs index 4d3f81d0e1..3bf614a3ef 100644 --- a/src/Umbraco.Core/Models/ContentBase.cs +++ b/src/Umbraco.Core/Models/ContentBase.cs @@ -21,7 +21,6 @@ namespace Umbraco.Core.Models { private static readonly Lazy Ps = new Lazy(); - private IDictionary _additionalData; private int _contentTypeId; protected IContentTypeComposition ContentTypeBase; private int _writerId; @@ -74,17 +73,6 @@ namespace Umbraco.Core.Models public readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo(x => x.WriterId); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [DataMember] - [DoNotClone] - IDictionary IUmbracoEntity.AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [IgnoreDataMember] - bool IUmbracoEntity.HasAdditionalData => _additionalData != null; - protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged(Ps.Value.PropertyCollectionSelector); diff --git a/src/Umbraco.Core/Models/ContentTypeBase.cs b/src/Umbraco.Core/Models/ContentTypeBase.cs index 9c9a93223c..ec7eddbaf6 100644 --- a/src/Umbraco.Core/Models/ContentTypeBase.cs +++ b/src/Umbraco.Core/Models/ContentTypeBase.cs @@ -21,7 +21,6 @@ namespace Umbraco.Core.Models { private static readonly Lazy Ps = new Lazy(); - private IDictionary _additionalData; private string _alias; private string _description; private string _icon = "icon-folder"; @@ -71,17 +70,6 @@ namespace Umbraco.Core.Models _variations = ContentVariation.InvariantNeutral; } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [DataMember] - [DoNotClone] - IDictionary IUmbracoEntity.AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [IgnoreDataMember] - bool IUmbracoEntity.HasAdditionalData => _additionalData != null; - /// /// Gets a value indicating whether the content type is publishing. /// diff --git a/src/Umbraco.Core/Models/DataType.cs b/src/Umbraco.Core/Models/DataType.cs index bc31c262f2..3914c74e3d 100644 --- a/src/Umbraco.Core/Models/DataType.cs +++ b/src/Umbraco.Core/Models/DataType.cs @@ -15,7 +15,6 @@ namespace Umbraco.Core.Models public class DataType : TreeEntityBase, IDataType { private static readonly Lazy Ps = new Lazy(); - private IDictionary _additionalData; private string _propertyEditorAlias; private DataTypeDatabaseType _databaseType; @@ -45,17 +44,6 @@ namespace Umbraco.Core.Models public readonly PropertyInfo DatabaseTypeSelector = ExpressionHelper.GetPropertyInfo(x => x.DatabaseType); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [DataMember] - [DoNotClone] - IDictionary IUmbracoEntity.AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [IgnoreDataMember] - bool IUmbracoEntity.HasAdditionalData => _additionalData != null; - /// [DataMember] public string EditorAlias diff --git a/src/Umbraco.Core/Models/Entities/IEntitySlim.cs b/src/Umbraco.Core/Models/Entities/IEntitySlim.cs index 356f891d00..8d443d6b3d 100644 --- a/src/Umbraco.Core/Models/Entities/IEntitySlim.cs +++ b/src/Umbraco.Core/Models/Entities/IEntitySlim.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Umbraco.Core.Models.Entities { @@ -21,5 +22,19 @@ namespace Umbraco.Core.Models.Entities /// Gets a value indicating whether the entity is a container. /// bool IsContainer { get; } + + /// + /// Gets additional data for this entity. + /// + /// Can be empty, but never null. To avoid allocating, do not + /// test for emptyness, but use instead. + IDictionary AdditionalData { get; } + + /// + /// Determines whether this entity has additional data. + /// + /// Use this property to check for additional data without + /// getting , to avoid allocating. + bool HasAdditionalData { get; } } } diff --git a/src/Umbraco.Core/Models/Entities/IUmbracoEntity.cs b/src/Umbraco.Core/Models/Entities/IUmbracoEntity.cs index ab775b781e..e5f628b098 100644 --- a/src/Umbraco.Core/Models/Entities/IUmbracoEntity.cs +++ b/src/Umbraco.Core/Models/Entities/IUmbracoEntity.cs @@ -11,19 +11,5 @@ namespace Umbraco.Core.Models.Entities /// An IUmbracoEntity can participate in notifications. /// public interface IUmbracoEntity : ITreeEntity, IRememberBeingDirty - { - /// - /// Gets additional data for this entity. - /// - /// Can be empty, but never null. To avoid allocating, do not - /// test for emptyness, but use instead. - IDictionary AdditionalData { get; } - - /// - /// Determines whether this entity has additional data. - /// - /// Use this property to check for additional data without - /// getting , to avoid allocating. - bool HasAdditionalData { get; } - } + { } } diff --git a/src/Umbraco.Core/Models/EntityContainer.cs b/src/Umbraco.Core/Models/EntityContainer.cs index 8a796a5691..70f6cbd878 100644 --- a/src/Umbraco.Core/Models/EntityContainer.cs +++ b/src/Umbraco.Core/Models/EntityContainer.cs @@ -13,7 +13,6 @@ namespace Umbraco.Core.Models public sealed class EntityContainer : TreeEntityBase, IUmbracoEntity { private readonly Guid _containedObjectType; - private IDictionary _additionalData; private static readonly Dictionary ObjectTypeMap = new Dictionary { @@ -87,16 +86,5 @@ namespace Umbraco.Core.Models throw new ArgumentException("Not a container object type.", nameof(containerObjectType)); return contained; } - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [DataMember] - [DoNotClone] - IDictionary IUmbracoEntity.AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [IgnoreDataMember] - bool IUmbracoEntity.HasAdditionalData => _additionalData != null; } } diff --git a/src/Umbraco.Core/Models/EntityExtensions.cs b/src/Umbraco.Core/Models/EntityExtensions.cs index 9929e73dda..84daf50585 100644 --- a/src/Umbraco.Core/Models/EntityExtensions.cs +++ b/src/Umbraco.Core/Models/EntityExtensions.cs @@ -18,5 +18,12 @@ namespace Umbraco.Core.Models { return entity.WasPropertyDirty("Id"); } + + // fixme - MOVE! + public static object GetAdditionalDataValueIgnoreCase(this IMember entity, string key, object defaultVal) + { + if (entity.AdditionalData.ContainsKeyIgnoreCase(key) == false) return defaultVal; + return entity.AdditionalData.GetValueIgnoreCase(key, defaultVal); + } } } diff --git a/src/Umbraco.Core/Models/IMember.cs b/src/Umbraco.Core/Models/IMember.cs index 28e011d7d0..f83c36de1a 100644 --- a/src/Umbraco.Core/Models/IMember.cs +++ b/src/Umbraco.Core/Models/IMember.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Umbraco.Core.Models.Membership; namespace Umbraco.Core.Models @@ -14,5 +15,19 @@ namespace Umbraco.Core.Models /// Gets the ContentType used by this content object /// IMemberType ContentType { get; } + + /// + /// Gets additional data for this entity. + /// + /// Can be empty, but never null. To avoid allocating, do not + /// test for emptyness, but use instead. + IDictionary AdditionalData { get; } + + /// + /// Determines whether this entity has additional data. + /// + /// Use this property to check for additional data without + /// getting , to avoid allocating. + bool HasAdditionalData { get; } } } diff --git a/src/Umbraco.Core/Models/Member.cs b/src/Umbraco.Core/Models/Member.cs index 553ae181cc..132584527c 100644 --- a/src/Umbraco.Core/Models/Member.cs +++ b/src/Umbraco.Core/Models/Member.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; using Umbraco.Core.Logging; +using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models { @@ -16,6 +18,7 @@ namespace Umbraco.Core.Models [DataContract(IsReference = true)] public class Member : ContentBase, IMember { + private IDictionary _additionalData; private IMemberType _contentType; private readonly string _contentTypeAlias; private string _username; @@ -588,5 +591,16 @@ namespace Umbraco.Core.Models return clone; } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + [DataMember] + [DoNotClone] + public IDictionary AdditionalData => _additionalData ?? (_additionalData = new Dictionary()); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + [IgnoreDataMember] + public bool HasAdditionalData => _additionalData != null; } } diff --git a/src/Umbraco.Core/Models/PathValidationExtensions.cs b/src/Umbraco.Core/Models/PathValidationExtensions.cs index e3c0b785e4..74c2c9faa5 100644 --- a/src/Umbraco.Core/Models/PathValidationExtensions.cs +++ b/src/Umbraco.Core/Models/PathValidationExtensions.cs @@ -88,7 +88,7 @@ namespace Umbraco.Core.Models if (entity.ValidatePath() == false) { - logger.Warn(typeof(UmbracoEntityExtensions), $"The content item {entity.Id} has an invalid path: {entity.Path} with parentID: {entity.ParentId}"); + logger.Warn(typeof(PathValidationExtensions), $"The content item {entity.Id} has an invalid path: {entity.Path} with parentID: {entity.ParentId}"); if (entity.ParentId == -1) { entity.Path = string.Concat("-1,", entity.Id); diff --git a/src/Umbraco.Core/Models/UmbracoEntityExtensions.cs b/src/Umbraco.Core/Models/UmbracoEntityExtensions.cs deleted file mode 100644 index e39be8b382..0000000000 --- a/src/Umbraco.Core/Models/UmbracoEntityExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Umbraco.Core.Models.Entities; - -namespace Umbraco.Core.Models -{ - // fixme - this needs to go or be refactored! - internal static class UmbracoEntityExtensions - { - public static object GetAdditionalDataValueIgnoreCase(this IUmbracoEntity entity, string key, object defaultVal) - { - if (entity.AdditionalData.ContainsKeyIgnoreCase(key) == false) return defaultVal; - return entity.AdditionalData.GetValueIgnoreCase(key, defaultVal); - } - } -} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index cae2a9ed85..80f508c652 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -773,7 +773,6 @@ - diff --git a/src/Umbraco.Tests/Models/ContentTests.cs b/src/Umbraco.Tests/Models/ContentTests.cs index 34f2966539..3ecc51fa29 100644 --- a/src/Umbraco.Tests/Models/ContentTests.cs +++ b/src/Umbraco.Tests/Models/ContentTests.cs @@ -212,9 +212,6 @@ namespace Umbraco.Tests.Models content.UpdateDate = DateTime.Now; content.WriterId = 23; - ((IUmbracoEntity)content).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)content).AdditionalData.Add("test2", "hello"); - var runtimeCache = new ObjectCacheRuntimeCacheProvider(); runtimeCache.InsertCacheItem(content.Id.ToString(CultureInfo.InvariantCulture), () => content); @@ -274,9 +271,6 @@ namespace Umbraco.Tests.Models content.UpdateDate = DateTime.Now; content.WriterId = 23; - ((IUmbracoEntity)content).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)content).AdditionalData.Add("test2", "hello"); - // Act var clone = (Content)content.DeepClone(); @@ -285,7 +279,6 @@ namespace Umbraco.Tests.Models Assert.AreEqual(clone, content); Assert.AreEqual(clone.Id, content.Id); Assert.AreEqual(clone.VersionId, content.VersionId); - Assert.AreEqual(((IUmbracoEntity)clone).AdditionalData, ((IUmbracoEntity)content).AdditionalData); Assert.AreNotSame(clone.ContentType, content.ContentType); Assert.AreEqual(clone.ContentType, content.ContentType); Assert.AreEqual(clone.ContentType.PropertyGroups.Count, content.ContentType.PropertyGroups.Count); @@ -380,9 +373,6 @@ namespace Umbraco.Tests.Models content.UpdateDate = DateTime.Now; content.WriterId = 23; - ((IUmbracoEntity)content).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)content).AdditionalData.Add("test2", "hello"); - var result = ss.ToStream(content); var json = result.ResultStream.ToJsonString(); Debug.Print(json); diff --git a/src/Umbraco.Tests/Models/ContentTypeTests.cs b/src/Umbraco.Tests/Models/ContentTypeTests.cs index 6efc2c8896..4176351d3d 100644 --- a/src/Umbraco.Tests/Models/ContentTypeTests.cs +++ b/src/Umbraco.Tests/Models/ContentTypeTests.cs @@ -137,9 +137,6 @@ namespace Umbraco.Tests.Models contentType.Trashed = false; contentType.UpdateDate = DateTime.Now; - ((IUmbracoEntity)contentType).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)contentType).AdditionalData.Add("test2", "hello"); - var proflog = GetTestProfilingLogger(); using (proflog.DebugDuration("STARTING PERF TEST")) @@ -190,9 +187,6 @@ namespace Umbraco.Tests.Models contentType.Trashed = false; contentType.UpdateDate = DateTime.Now; - ((IUmbracoEntity)contentType).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)contentType).AdditionalData.Add("test2", "hello"); - // Act var clone = (ContentType)contentType.DeepClone(); @@ -200,7 +194,6 @@ namespace Umbraco.Tests.Models Assert.AreNotSame(clone, contentType); Assert.AreEqual(clone, contentType); Assert.AreEqual(clone.Id, contentType.Id); - Assert.AreEqual(((IUmbracoEntity)clone).AdditionalData, ((IUmbracoEntity)contentType).AdditionalData); Assert.AreEqual(clone.AllowedTemplates.Count(), contentType.AllowedTemplates.Count()); for (var index = 0; index < contentType.AllowedTemplates.Count(); index++) { @@ -291,9 +284,6 @@ namespace Umbraco.Tests.Models contentType.Trashed = false; contentType.UpdateDate = DateTime.Now; - ((IUmbracoEntity)contentType).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)contentType).AdditionalData.Add("test2", "hello"); - var result = ss.ToStream(contentType); var json = result.ResultStream.ToJsonString(); Debug.Print(json); @@ -325,9 +315,6 @@ namespace Umbraco.Tests.Models contentType.Trashed = false; contentType.UpdateDate = DateTime.Now; - ((IUmbracoEntity)contentType).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)contentType).AdditionalData.Add("test2", "hello"); - // Act var clone = (MediaType)contentType.DeepClone(); @@ -335,7 +322,6 @@ namespace Umbraco.Tests.Models Assert.AreNotSame(clone, contentType); Assert.AreEqual(clone, contentType); Assert.AreEqual(clone.Id, contentType.Id); - Assert.AreEqual(((IUmbracoEntity)clone).AdditionalData, ((IUmbracoEntity)contentType).AdditionalData); Assert.AreEqual(clone.PropertyGroups.Count, contentType.PropertyGroups.Count); for (var index = 0; index < contentType.PropertyGroups.Count; index++) { @@ -396,9 +382,6 @@ namespace Umbraco.Tests.Models contentType.Trashed = false; contentType.UpdateDate = DateTime.Now; - ((IUmbracoEntity)contentType).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)contentType).AdditionalData.Add("test2", "hello"); - var result = ss.ToStream(contentType); var json = result.ResultStream.ToJsonString(); Debug.Print(json); @@ -431,8 +414,6 @@ namespace Umbraco.Tests.Models contentType.UpdateDate = DateTime.Now; contentType.SetMemberCanEditProperty("title", true); contentType.SetMemberCanViewProperty("bodyText", true); - ((IUmbracoEntity)contentType).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)contentType).AdditionalData.Add("test2", "hello"); // Act var clone = (MemberType)contentType.DeepClone(); @@ -441,7 +422,6 @@ namespace Umbraco.Tests.Models Assert.AreNotSame(clone, contentType); Assert.AreEqual(clone, contentType); Assert.AreEqual(clone.Id, contentType.Id); - Assert.AreEqual(((IUmbracoEntity)clone).AdditionalData, ((IUmbracoEntity)contentType).AdditionalData); Assert.AreEqual(clone.PropertyGroups.Count, contentType.PropertyGroups.Count); for (var index = 0; index < contentType.PropertyGroups.Count; index++) { @@ -504,8 +484,6 @@ namespace Umbraco.Tests.Models contentType.UpdateDate = DateTime.Now; contentType.SetMemberCanEditProperty("title", true); contentType.SetMemberCanViewProperty("bodyText", true); - ((IUmbracoEntity)contentType).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)contentType).AdditionalData.Add("test2", "hello"); var result = ss.ToStream(contentType); var json = result.ResultStream.ToJsonString(); diff --git a/src/Umbraco.Tests/Models/MemberTests.cs b/src/Umbraco.Tests/Models/MemberTests.cs index c1e3798192..76ea804c57 100644 --- a/src/Umbraco.Tests/Models/MemberTests.cs +++ b/src/Umbraco.Tests/Models/MemberTests.cs @@ -45,8 +45,8 @@ namespace Umbraco.Tests.Models member.SortOrder = 5; member.Trashed = false; member.UpdateDate = DateTime.Now; - ((IUmbracoEntity)member).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)member).AdditionalData.Add("test2", "hello"); + member.AdditionalData.Add("test1", 123); + member.AdditionalData.Add("test2", "hello"); // Act var clone = (Member)member.DeepClone(); @@ -56,7 +56,7 @@ namespace Umbraco.Tests.Models Assert.AreEqual(clone, member); Assert.AreEqual(clone.Id, member.Id); Assert.AreEqual(clone.VersionId, member.VersionId); - Assert.AreEqual(((IUmbracoEntity)clone).AdditionalData, ((IUmbracoEntity)member).AdditionalData); + Assert.AreEqual(clone.AdditionalData, member.AdditionalData); Assert.AreNotSame(clone.ContentType, member.ContentType); Assert.AreEqual(clone.ContentType, member.ContentType); Assert.AreEqual(clone.ContentType.PropertyGroups.Count, member.ContentType.PropertyGroups.Count); @@ -144,8 +144,8 @@ namespace Umbraco.Tests.Models member.SortOrder = 5; member.Trashed = false; member.UpdateDate = DateTime.Now; - ((IUmbracoEntity)member).AdditionalData.Add("test1", 123); - ((IUmbracoEntity)member).AdditionalData.Add("test2", "hello"); + member.AdditionalData.Add("test1", 123); + member.AdditionalData.Add("test2", "hello"); var result = ss.ToStream(member); var json = result.ResultStream.ToJsonString(); diff --git a/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs b/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs index 9e19c39430..e844d97705 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberMapperProfile.cs @@ -198,6 +198,7 @@ namespace Umbraco.Web.Models.Mapping // only when creating a new member and we want to have a generated password pre-filled. Value = new Dictionary { + // fixme why ignoreCase, what are we doing here?! {"generatedPassword", member.GetAdditionalDataValueIgnoreCase("GeneratedPassword", null)}, {"newPassword", member.GetAdditionalDataValueIgnoreCase("NewPassword", null)}, },