Merge commit '94d525d88f713b36419f28bfda4d82ee68637d83' into v9/dev

# Conflicts:
#	build/NuSpecs/UmbracoCms.Web.nuspec
#	src/Umbraco.Core/Composing/Current.cs
#	src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs
#	src/Umbraco.Core/Runtime/CoreRuntime.cs
#	src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs
#	src/Umbraco.Infrastructure/Persistence/NPocoDatabaseExtensions.cs
#	src/Umbraco.Infrastructure/Persistence/UmbracoDatabase.cs
#	src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/BTree.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataModel.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataSerializationResult.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataSerializerEntityType.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/ContentData.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/ContentNestedData.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/CultureVariation.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/IContentCacheDataSerializer.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/IContentCacheDataSerializerFactory.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/IDictionaryOfPropertyDataSerializer.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializer.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializerFactory.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/LazyCompressedString.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/MsgPackContentNestedDataSerializer.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/MsgPackContentNestedDataSerializerFactory.cs
#	src/Umbraco.PublishedCache.NuCache/DataSource/PropertyData.cs
#	src/Umbraco.PublishedCache.NuCache/NuCacheSerializerComponent.cs
#	src/Umbraco.PublishedCache.NuCache/NuCacheSerializerComposer.cs
#	src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs
#	src/Umbraco.Tests/App.config
#	src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs
#	src/Umbraco.Tests/PublishedContent/NuCacheTests.cs
#	src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs
#	src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml
#	src/Umbraco.Web.UI/web.Template.Debug.config
#	src/Umbraco.Web.UI/web.Template.config
#	src/Umbraco.Web/Composing/ModuleInjector.cs
#	src/Umbraco.Web/Editors/NuCacheStatusController.cs
#	src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentNestedData.cs
#	src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs
#	src/Umbraco.Web/PublishedCache/NuCache/NuCacheComposer.cs
#	src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs
#	src/Umbraco.Web/Runtime/WebRuntime.cs
This commit is contained in:
Shannon
2021-06-24 09:43:57 -06:00
parent 4c89d036ac
commit 72671dbca8
139 changed files with 5650 additions and 1593 deletions

View File

@@ -0,0 +1,37 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Umbraco.Cms.Infrastructure.Serialization
{
/// <summary>
/// When applied to a string or string collection field will ensure the deserialized strings are interned
/// </summary>
/// <remarks>
/// Borrowed from https://stackoverflow.com/a/34906004/694494
/// On the same page an interesting approach of using a local intern pool https://stackoverflow.com/a/39605620/694494 which re-uses .NET System.Xml.NameTable
/// </remarks>
public class AutoInterningStringConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// CanConvert is not called when a converter is applied directly to a property.
throw new NotImplementedException($"{nameof(AutoInterningStringConverter)} should not be used globally");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
// Check is in case the value is a non-string literal such as an integer.
var s = reader.TokenType == JsonToken.String
? string.Intern((string)reader.Value)
: string.Intern((string)JToken.Load(reader));
return s;
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Umbraco.Cms.Infrastructure.Serialization
{
/// <summary>
/// When applied to a dictionary with a string key, will ensure the deserialized string keys are interned
/// </summary>
/// <typeparam name="TValue"></typeparam>
/// <remarks>
/// borrowed from https://stackoverflow.com/a/36116462/694494
/// </remarks>
public class AutoInterningStringKeyCaseInsensitiveDictionaryConverter<TValue> : CaseInsensitiveDictionaryConverter<TValue>
{
public AutoInterningStringKeyCaseInsensitiveDictionaryConverter()
{
}
public AutoInterningStringKeyCaseInsensitiveDictionaryConverter(StringComparer comparer) : base(comparer)
{
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject)
{
var dictionary = new Dictionary<string, TValue>();
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.PropertyName:
var key = string.Intern(reader.Value.ToString());
if (!reader.Read())
throw new Exception("Unexpected end when reading object.");
var v = serializer.Deserialize<TValue>(reader);
dictionary[key] = v;
break;
case JsonToken.Comment:
break;
case JsonToken.EndObject:
return dictionary;
}
}
}
return null;
}
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json.Converters;
@@ -14,12 +14,24 @@ namespace Umbraco.Cms.Infrastructure.Serialization
/// </example>
public class CaseInsensitiveDictionaryConverter<T> : CustomCreationConverter<IDictionary>
{
private readonly StringComparer _comparer;
public CaseInsensitiveDictionaryConverter()
: this(StringComparer.OrdinalIgnoreCase)
{
}
public CaseInsensitiveDictionaryConverter(StringComparer comparer)
{
_comparer = comparer ?? throw new ArgumentNullException(nameof(comparer));
}
public override bool CanWrite => false;
public override bool CanRead => true;
public override bool CanConvert(Type objectType) => typeof(IDictionary<string,T>).IsAssignableFrom(objectType);
public override IDictionary Create(Type objectType) => new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
public override IDictionary Create(Type objectType) => new Dictionary<string, T>(_comparer);
}
}