v10: Fix Block List settings exception and optimize PVCs (#12342)
* Don't use MapModelType to get model type * Optimize block list item activation (cache constructors) * Fix exceptions in NestedContentSingleValueConverter (zero content types or multiple stored items) * Add IPublishedModelFactory.GetModelType method to remove work-around
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
@@ -59,20 +57,27 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
if (parms.Length == 2 && typeof(IPublishedElement).IsAssignableFrom(parms[0].ParameterType) && typeof(IPublishedValueFallback).IsAssignableFrom(parms[1].ParameterType))
|
||||
{
|
||||
if (constructor != null)
|
||||
{
|
||||
throw new InvalidOperationException($"Type {type.FullName} has more than one public constructor with one argument of type, or implementing, IPublishedElement.");
|
||||
}
|
||||
|
||||
constructor = ctor;
|
||||
parameterType = parms[0].ParameterType;
|
||||
}
|
||||
}
|
||||
|
||||
if (constructor == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Type {type.FullName} is missing a public constructor with one argument of type, or implementing, IPublishedElement.");
|
||||
}
|
||||
|
||||
var attribute = type.GetCustomAttribute<PublishedModelAttribute>(false);
|
||||
var typeName = attribute == null ? type.Name : attribute.ContentTypeAlias;
|
||||
|
||||
if (modelInfos.TryGetValue(typeName, out var modelInfo))
|
||||
{
|
||||
throw new InvalidOperationException($"Both types '{type.AssemblyQualifiedName}' and '{modelInfo.ModelType?.AssemblyQualifiedName}' want to be a model type for content type with alias \"{typeName}\".");
|
||||
}
|
||||
|
||||
// have to use an unsafe ctor because we don't know the types, really
|
||||
var modelCtor = ReflectionUtilities.EmitConstructorUnsafe<Func<object, IPublishedValueFallback, object>>(constructor);
|
||||
@@ -89,15 +94,16 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
public IPublishedElement CreateModel(IPublishedElement element)
|
||||
{
|
||||
// fail fast
|
||||
if (_modelInfos == null)
|
||||
return element;
|
||||
|
||||
if (element.ContentType.Alias is null || !_modelInfos.TryGetValue(element.ContentType.Alias, out var modelInfo))
|
||||
if (_modelInfos is null || element.ContentType.Alias is null || !_modelInfos.TryGetValue(element.ContentType.Alias, out var modelInfo))
|
||||
{
|
||||
return element;
|
||||
}
|
||||
|
||||
// ReSharper disable once UseMethodIsInstanceOfType
|
||||
if (modelInfo.ParameterType?.IsAssignableFrom(element.GetType()) == false)
|
||||
{
|
||||
throw new InvalidOperationException($"Model {modelInfo.ModelType} expects argument of type {modelInfo.ParameterType.FullName}, but got {element.GetType().FullName}.");
|
||||
}
|
||||
|
||||
// can cast, because we checked when creating the ctor
|
||||
return (IPublishedElement)modelInfo.Ctor!(element, _publishedValueFallback);
|
||||
@@ -107,21 +113,42 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
public IList? CreateModelList(string? alias)
|
||||
{
|
||||
// fail fast
|
||||
if (_modelInfos == null)
|
||||
return new List<IPublishedElement>();
|
||||
|
||||
if (alias is null || !_modelInfos.TryGetValue(alias, out var modelInfo) || modelInfo.ModelType is null)
|
||||
if (_modelInfos is null || alias is null || !_modelInfos.TryGetValue(alias, out var modelInfo) || modelInfo.ModelType is null)
|
||||
{
|
||||
return new List<IPublishedElement>();
|
||||
}
|
||||
|
||||
var ctor = modelInfo.ListCtor;
|
||||
if (ctor != null) return ctor();
|
||||
if (ctor != null)
|
||||
{
|
||||
return ctor();
|
||||
}
|
||||
|
||||
var listType = typeof(List<>).MakeGenericType(modelInfo.ModelType);
|
||||
ctor = modelInfo.ListCtor = ReflectionUtilities.EmitConstructor<Func<IList>>(declaring: listType);
|
||||
if(ctor is not null) return ctor();
|
||||
if (ctor is not null)
|
||||
{
|
||||
return ctor();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type GetModelType(string? alias)
|
||||
{
|
||||
// fail fast
|
||||
if (_modelInfos is null ||
|
||||
alias is null ||
|
||||
!_modelInfos.TryGetValue(alias, out var modelInfo) ||
|
||||
modelInfo.ModelType is null)
|
||||
{
|
||||
return typeof(IPublishedElement);
|
||||
}
|
||||
|
||||
return modelInfo.ModelType;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type MapModelType(Type type)
|
||||
=> ModelType.Map(type, _modelTypeMap);
|
||||
|
||||
Reference in New Issue
Block a user