PropertyValueConverter - more WIP

This commit is contained in:
Stephan
2017-07-27 11:09:53 +02:00
parent 76569d58fe
commit 4bfea6044a
10 changed files with 551 additions and 148 deletions

View File

@@ -14,11 +14,13 @@ namespace Umbraco.Core.Models.PublishedContent
private readonly PublishedPropertyType[] _propertyTypes;
// fast alias-to-index xref containing both the raw alias and its lowercase version
// fixme - benchmark this!
private readonly Dictionary<string, int> _indexes = new Dictionary<string, int>();
// internal so it can be used by PublishedNoCache which does _not_ want to cache anything and so will never
// use the static cache getter PublishedContentType.GetPublishedContentType(alias) below - anything else
// should use it.
// fixme - not true anymore internal and all?!
internal PublishedContentType(IContentType contentType)
: this(PublishedItemType.Content, contentType)
{ }
@@ -88,7 +90,7 @@ namespace Umbraco.Core.Models.PublishedContent
// NOTE: code below defines and add custom, built-in, Umbraco properties for members
// unless they are already user-defined in the content type, then they are skipped
// not sure it's needed really - this is here for safety purposes
static readonly Dictionary<string, Tuple<int, string>> BuiltinMemberProperties = new Dictionary<string, Tuple<int, string>>
private static readonly Dictionary<string, Tuple<int, string>> BuiltinMemberProperties = new Dictionary<string, Tuple<int, string>>
{
// see also PublishedMember class - exposing special properties as properties
{ "Email", Tuple.Create(Constants.DataTypes.Textbox, Constants.PropertyEditors.TextboxAlias) },
@@ -115,7 +117,7 @@ namespace Umbraco.Core.Models.PublishedContent
foreach (var propertyType in BuiltinMemberProperties
.Where(kvp => aliases.Contains(kvp.Key) == false)
.Select(kvp => new PublishedPropertyType(kvp.Key, kvp.Value.Item1, kvp.Value.Item2, true)))
.Select(kvp => new PublishedPropertyType(kvp.Key, kvp.Value.Item1, kvp.Value.Item2, umbraco: true)))
{
if (contentType != null) propertyType.ContentType = contentType;
yield return propertyType;

View File

@@ -13,6 +13,23 @@ namespace Umbraco.Core.Models.PublishedContent
{
PropertyType = propertyType ?? throw new ArgumentNullException(nameof(propertyType));
ReferenceCacheLevel = referenceCacheLevel;
ValidateCacheLevel(ReferenceCacheLevel);
ValidateCacheLevel(PropertyType.CacheLevel);
}
private static void ValidateCacheLevel(PropertyCacheLevel cacheLevel)
{
switch (cacheLevel)
{
case PropertyCacheLevel.Content:
case PropertyCacheLevel.Snapshot:
case PropertyCacheLevel.Facade:
case PropertyCacheLevel.None:
break;
default:
throw new Exception("Invalid cache level.");
}
}
public PublishedPropertyType PropertyType { get; }

View File

@@ -13,6 +13,15 @@ namespace Umbraco.Core.Models.PublishedContent
/// if the property type changes, then a new class needs to be created.</remarks>
public class PublishedPropertyType
{
private readonly PropertyValueConverterCollection _converters;
private readonly object _locker = new object();
private volatile bool _initialized;
private IPropertyValueConverter _converter;
private PropertyCacheLevel _cacheLevel;
private Type _modelClrType;
private Type _clrType;
#region Constructors
/// <summary>
@@ -26,6 +35,8 @@ namespace Umbraco.Core.Models.PublishedContent
{
// PropertyEditor [1:n] DataTypeDefinition [1:n] PropertyType
_converters = Current.PropertyValueConverters; // fixme really?
ContentType = contentType;
PropertyTypeAlias = propertyType.Alias;
@@ -46,8 +57,8 @@ namespace Umbraco.Core.Models.PublishedContent
/// to make decisions, fetch prevalues, etc.</para>
/// <para>The value of <paramref name="propertyEditorAlias"/> is assumed to be valid.</para>
/// </remarks>
internal PublishedPropertyType(string propertyTypeAlias, string propertyEditorAlias)
: this(propertyTypeAlias, 0, propertyEditorAlias)
internal PublishedPropertyType(string propertyTypeAlias, string propertyEditorAlias, PropertyValueConverterCollection converters = null)
: this(propertyTypeAlias, 0, propertyEditorAlias, converters)
{ }
/// <summary>
@@ -63,11 +74,13 @@ namespace Umbraco.Core.Models.PublishedContent
/// <para>The values of <paramref name="dataTypeDefinitionId"/> and <paramref name="propertyEditorAlias"/> are
/// assumed to be valid and consistent.</para>
/// </remarks>
internal PublishedPropertyType(string propertyTypeAlias, int dataTypeDefinitionId, string propertyEditorAlias, bool umbraco = false)
internal PublishedPropertyType(string propertyTypeAlias, int dataTypeDefinitionId, string propertyEditorAlias, PropertyValueConverterCollection converters = null, bool umbraco = false)
{
// ContentType
// - in unit tests, to be set by PublishedContentType when creating it
_converters = converters ?? Current.PropertyValueConverters; // fixme really?
PropertyTypeAlias = propertyTypeAlias;
DataTypeId = dataTypeDefinitionId;
@@ -109,32 +122,23 @@ namespace Umbraco.Core.Models.PublishedContent
#region Converters
private readonly object _locker = new object();
private volatile bool _initialized;
private IPropertyValueConverter _converter;
private PropertyCacheLevel _cacheLevel;
private Type _modelClrType;
private Type _clrType;
private void EnsureInitialized()
private void Initialize()
{
if (_initialized) return;
lock (_locker)
{
if (_initialized) return;
InitializeConverters();
InitializeLocked();
_initialized = true;
}
}
private void InitializeConverters()
private void InitializeLocked()
{
_converter = null;
var isdefault = false;
var converterCollection = Current.PropertyValueConverters;
foreach (var converter in converterCollection)
foreach (var converter in _converters)
{
if (converter.IsConverter(this) == false)
continue;
@@ -142,20 +146,20 @@ namespace Umbraco.Core.Models.PublishedContent
if (_converter == null)
{
_converter = converter;
isdefault = converterCollection.IsDefault(converter);
isdefault = _converters.IsDefault(converter);
continue;
}
if (isdefault)
{
if (converterCollection.IsDefault(converter))
if (_converters.IsDefault(converter))
{
// previous was default, and got another default
if (converterCollection.Shadows(_converter, converter))
if (_converters.Shadows(_converter, converter))
{
// previous shadows, ignore
}
else if (converterCollection.Shadows(converter, _converter))
else if (_converters.Shadows(converter, _converter))
{
// shadows previous, replace
_converter = converter;
@@ -179,7 +183,7 @@ namespace Umbraco.Core.Models.PublishedContent
}
else
{
if (converterCollection.IsDefault(converter))
if (_converters.IsDefault(converter))
{
// previous was non-default, ignore default
}
@@ -204,7 +208,7 @@ namespace Umbraco.Core.Models.PublishedContent
{
get
{
EnsureInitialized();
if (!_initialized) Initialize();
return _cacheLevel;
}
}
@@ -215,7 +219,7 @@ namespace Umbraco.Core.Models.PublishedContent
// preview: whether we are previewing or not
public object ConvertSourceToInter(IPropertySet owner, object source, bool preview)
{
EnsureInitialized();
if (!_initialized) Initialize();
// use the converter if any, else just return the source value
return _converter != null
@@ -229,7 +233,7 @@ namespace Umbraco.Core.Models.PublishedContent
// preview: whether we are previewing or not
public object ConvertInterToObject(IPropertySet owner, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
{
EnsureInitialized();
if (!_initialized) Initialize();
// use the converter if any, else just return the inter value
return _converter != null
@@ -244,7 +248,7 @@ namespace Umbraco.Core.Models.PublishedContent
// preview: whether we are previewing or not
public object ConvertInterToXPath(IPropertySet owner, PropertyCacheLevel referenceCacheLevel, object inter, bool preview)
{
EnsureInitialized();
if (!_initialized) Initialize();
// use the converter if any
if (_converter != null)
@@ -264,7 +268,7 @@ namespace Umbraco.Core.Models.PublishedContent
{
get
{
EnsureInitialized();
if (!_initialized) Initialize();
return _modelClrType;
}
}
@@ -276,7 +280,7 @@ namespace Umbraco.Core.Models.PublishedContent
{
get
{
EnsureInitialized();
if (!_initialized) Initialize();
return _clrType ?? (_clrType = ModelType.Map(_modelClrType, Current.PublishedContentModelFactory.ModelTypeMap));
}
}