Moved more abstractions of models

This commit is contained in:
Bjarke Berg
2019-05-27 11:54:17 +02:00
parent dcf022ffaa
commit 00a121188a
24 changed files with 33 additions and 56 deletions

View File

@@ -1,75 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// Manages the built-in fallback policies.
/// </summary>
public struct Fallback : IEnumerable<int>
{
private readonly int[] _values;
/// <summary>
/// Initializes a new instance of the <see cref="Fallback"/> struct with values.
/// </summary>
private Fallback(int[] values)
{
_values = values;
}
/// <summary>
/// Gets an ordered set of fallback policies.
/// </summary>
/// <param name="values"></param>
public static Fallback To(params int[] values) => new Fallback(values);
/// <summary>
/// Do not fallback.
/// </summary>
public const int None = 0;
/// <summary>
/// Fallback to default value.
/// </summary>
public const int DefaultValue = 1;
/// <summary>
/// Gets the fallback to default value policy.
/// </summary>
public static Fallback ToDefaultValue => new Fallback(new[] { DefaultValue });
/// <summary>
/// Fallback to other languages.
/// </summary>
public const int Language = 2;
/// <summary>
/// Gets the fallback to language policy.
/// </summary>
public static Fallback ToLanguage => new Fallback(new[] { Language });
/// <summary>
/// Fallback to tree ancestors.
/// </summary>
public const int Ancestors = 3;
/// <summary>
/// Gets the fallback to tree ancestors policy.
/// </summary>
public static Fallback ToAncestors => new Fallback(new[] { Ancestors });
/// <inheritdoc />
public IEnumerator<int> GetEnumerator()
{
return ((IEnumerable<int>)_values ?? Array.Empty<int>()).GetEnumerator();
}
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -1,13 +0,0 @@
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// Gives access to the current <see cref="VariationContext"/>.
/// </summary>
public interface IVariationContextAccessor
{
/// <summary>
/// Gets or sets the current <see cref="VariationContext"/>.
/// </summary>
VariationContext VariationContext { get; set; }
}
}

View File

@@ -1,411 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Models.PublishedContent
{
/// <inheritdoc />
/// <summary>
/// Represents the CLR type of a model.
/// </summary>
/// <example>
/// ModelType.For("alias")
/// typeof (IEnumerable{}).MakeGenericType(ModelType.For("alias"))
/// Model.For("alias").MakeArrayType()
/// </example>
public class ModelType : Type
{
private ModelType(string contentTypeAlias)
{
if (string.IsNullOrWhiteSpace(contentTypeAlias)) throw new ArgumentNullOrEmptyException(nameof(contentTypeAlias));
ContentTypeAlias = contentTypeAlias;
Name = "{" + ContentTypeAlias + "}";
}
/// <summary>
/// Gets the content type alias.
/// </summary>
public string ContentTypeAlias { get; }
/// <inheritdoc />
public override string ToString()
=> Name;
/// <summary>
/// Gets the model type for a published element type.
/// </summary>
/// <param name="alias">The published element type alias.</param>
/// <returns>The model type for the published element type.</returns>
public static ModelType For(string alias)
=> new ModelType(alias);
/// <summary>
/// Gets the actual CLR type by replacing model types, if any.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="modelTypes">The model types map.</param>
/// <returns>The actual CLR type.</returns>
public static Type Map(Type type, Dictionary<string, Type> modelTypes)
=> Map(type, modelTypes, false);
public static Type Map(Type type, Dictionary<string, Type> modelTypes, bool dictionaryIsInvariant)
{
// it may be that senders forgot to send an invariant dictionary (garbage-in)
if (!dictionaryIsInvariant)
modelTypes = new Dictionary<string, Type>(modelTypes, StringComparer.InvariantCultureIgnoreCase);
if (type is ModelType modelType)
{
if (modelTypes.TryGetValue(modelType.ContentTypeAlias, out var actualType))
return actualType;
throw new InvalidOperationException($"Don't know how to map ModelType with content type alias \"{modelType.ContentTypeAlias}\".");
}
if (type is ModelTypeArrayType arrayType)
{
if (modelTypes.TryGetValue(arrayType.ContentTypeAlias, out var actualType))
return actualType.MakeArrayType();
throw new InvalidOperationException($"Don't know how to map ModelType with content type alias \"{arrayType.ContentTypeAlias}\".");
}
if (type.IsGenericType == false)
return type;
var def = type.GetGenericTypeDefinition();
if (def == null)
throw new InvalidOperationException("panic");
var args = type.GetGenericArguments().Select(x => Map(x, modelTypes, true)).ToArray();
return def.MakeGenericType(args);
}
/// <summary>
/// Gets the actual CLR type name by replacing model types, if any.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="map">The model types map.</param>
/// <returns>The actual CLR type name.</returns>
public static string MapToName(Type type, Dictionary<string, string> map)
=> MapToName(type, map, false);
private static string MapToName(Type type, Dictionary<string, string> map, bool dictionaryIsInvariant)
{
// it may be that senders forgot to send an invariant dictionary (garbage-in)
if (!dictionaryIsInvariant)
map = new Dictionary<string, string>(map, StringComparer.InvariantCultureIgnoreCase);
if (type is ModelType modelType)
{
if (map.TryGetValue(modelType.ContentTypeAlias, out var actualTypeName))
return actualTypeName;
throw new InvalidOperationException($"Don't know how to map ModelType with content type alias \"{modelType.ContentTypeAlias}\".");
}
if (type is ModelTypeArrayType arrayType)
{
if (map.TryGetValue(arrayType.ContentTypeAlias, out var actualTypeName))
return actualTypeName + "[]";
throw new InvalidOperationException($"Don't know how to map ModelType with content type alias \"{arrayType.ContentTypeAlias}\".");
}
if (type.IsGenericType == false)
return type.FullName;
var def = type.GetGenericTypeDefinition();
if (def == null)
throw new InvalidOperationException("panic");
var args = type.GetGenericArguments().Select(x => MapToName(x, map, true)).ToArray();
var defFullName = def.FullName.Substring(0, def.FullName.IndexOf('`'));
return defFullName + "<" + string.Join(", ", args) + ">";
}
/// <summary>
/// Gets a value indicating whether two <see cref="Type"/> instances are equal.
/// </summary>
/// <param name="t1">The first instance.</param>
/// <param name="t2">The second instance.</param>
/// <returns>A value indicating whether the two instances are equal.</returns>
/// <remarks>Knows how to compare <see cref="ModelType"/> instances.</remarks>
public static bool Equals(Type t1, Type t2)
{
if (t1 == t2)
return true;
if (t1 is ModelType m1 && t2 is ModelType m2)
return m1.ContentTypeAlias == m2.ContentTypeAlias;
if (t1 is ModelTypeArrayType a1 && t2 is ModelTypeArrayType a2)
return a1.ContentTypeAlias == a2.ContentTypeAlias;
if (t1.IsGenericType == false || t2.IsGenericType == false)
return false;
var args1 = t1.GetGenericArguments();
var args2 = t2.GetGenericArguments();
if (args1.Length != args2.Length) return false;
for (var i = 0; i < args1.Length; i++)
{
// ReSharper disable once CheckForReferenceEqualityInstead.2
if (Equals(args1[i], args2[i]) == false) return false;
}
return true;
}
/// <inheritdoc />
protected override TypeAttributes GetAttributeFlagsImpl()
=> TypeAttributes.Class;
/// <inheritdoc />
public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
=> Array.Empty<ConstructorInfo>();
/// <inheritdoc />
protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
=> null;
/// <inheritdoc />
public override Type[] GetInterfaces()
=> Array.Empty<Type>();
/// <inheritdoc />
public override Type GetInterface(string name, bool ignoreCase)
=> null;
/// <inheritdoc />
public override EventInfo[] GetEvents(BindingFlags bindingAttr)
=> Array.Empty<EventInfo>();
/// <inheritdoc />
public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
=> null;
/// <inheritdoc />
public override Type[] GetNestedTypes(BindingFlags bindingAttr)
=> Array.Empty<Type>();
/// <inheritdoc />
public override Type GetNestedType(string name, BindingFlags bindingAttr)
=> null;
/// <inheritdoc />
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
=> Array.Empty<PropertyInfo>();
/// <inheritdoc />
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
=> null;
/// <inheritdoc />
public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
=> Array.Empty<MethodInfo>();
/// <inheritdoc />
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
=> null;
/// <inheritdoc />
public override FieldInfo[] GetFields(BindingFlags bindingAttr)
=> Array.Empty<FieldInfo>();
/// <inheritdoc />
public override FieldInfo GetField(string name, BindingFlags bindingAttr)
=> null;
/// <inheritdoc />
public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
=> Array.Empty<MemberInfo>();
/// <inheritdoc />
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
=> Array.Empty<object>();
/// <inheritdoc />
public override object[] GetCustomAttributes(bool inherit)
=> Array.Empty<object>();
/// <inheritdoc />
public override bool IsDefined(Type attributeType, bool inherit)
=> false;
/// <inheritdoc />
public override Type GetElementType()
=> null;
/// <inheritdoc />
protected override bool HasElementTypeImpl()
=> false;
/// <inheritdoc />
protected override bool IsArrayImpl()
=> false;
/// <inheritdoc />
protected override bool IsByRefImpl()
=> false;
/// <inheritdoc />
protected override bool IsPointerImpl()
=> false;
/// <inheritdoc />
protected override bool IsPrimitiveImpl()
=> false;
/// <inheritdoc />
protected override bool IsCOMObjectImpl()
=> false;
/// <inheritdoc />
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
=> throw new NotSupportedException();
/// <inheritdoc />
public override Type UnderlyingSystemType => this;
/// <inheritdoc />
public override Type BaseType => null;
/// <inheritdoc />
public override string Name { get; }
/// <inheritdoc />
public override Guid GUID { get; } = Guid.NewGuid();
/// <inheritdoc />
public override Module Module => GetType().Module; // hackish but FullName requires something
/// <inheritdoc />
public override Assembly Assembly => GetType().Assembly; // hackish but FullName requires something
/// <inheritdoc />
public override string FullName => Name;
/// <inheritdoc />
public override string Namespace => string.Empty;
/// <inheritdoc />
public override string AssemblyQualifiedName => Name;
/// <inheritdoc />
public override Type MakeArrayType()
=> new ModelTypeArrayType(this);
}
internal class ModelTypeArrayType : Type
{
private readonly Type _elementType;
public ModelTypeArrayType(ModelType type)
{
_elementType = type;
ContentTypeAlias = type.ContentTypeAlias;
Name = "{" + type.ContentTypeAlias + "}[*]";
}
public string ContentTypeAlias { get; }
public override string ToString()
=> Name;
protected override TypeAttributes GetAttributeFlagsImpl()
=> TypeAttributes.Class;
public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
=> Array.Empty<ConstructorInfo>();
protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
=> null;
public override Type[] GetInterfaces()
=> Array.Empty<Type>();
public override Type GetInterface(string name, bool ignoreCase)
=> null;
public override EventInfo[] GetEvents(BindingFlags bindingAttr)
=> Array.Empty<EventInfo>();
public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
=> null;
public override Type[] GetNestedTypes(BindingFlags bindingAttr)
=> Array.Empty<Type>();
public override Type GetNestedType(string name, BindingFlags bindingAttr)
=> null;
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
=> Array.Empty<PropertyInfo>();
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
=> null;
public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
=> Array.Empty<MethodInfo>();
protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
=> null;
public override FieldInfo[] GetFields(BindingFlags bindingAttr)
=> Array.Empty<FieldInfo>();
public override FieldInfo GetField(string name, BindingFlags bindingAttr)
=> null;
public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
=> Array.Empty<MemberInfo>();
public override object[] GetCustomAttributes(Type attributeType, bool inherit)
=> Array.Empty<object>();
public override object[] GetCustomAttributes(bool inherit)
=> Array.Empty<object>();
public override bool IsDefined(Type attributeType, bool inherit)
=> false;
public override Type GetElementType()
=> _elementType;
protected override bool HasElementTypeImpl()
=> true;
protected override bool IsArrayImpl()
=> true;
protected override bool IsByRefImpl()
=> false;
protected override bool IsPointerImpl()
=> false;
protected override bool IsPrimitiveImpl()
=> false;
protected override bool IsCOMObjectImpl()
=> false;
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
{
throw new NotSupportedException();
}
public override Type UnderlyingSystemType => this;
public override Type BaseType => null;
public override string Name { get; }
public override Guid GUID { get; } = Guid.NewGuid();
public override Module Module =>GetType().Module; // hackish but FullName requires something
public override Assembly Assembly => GetType().Assembly; // hackish but FullName requires something
public override string FullName => Name;
public override string Namespace => string.Empty;
public override string AssemblyQualifiedName => Name;
public override int GetArrayRank()
=> 1;
}
}

View File

@@ -1,50 +0,0 @@
using System;
using Umbraco.Core.Exceptions;
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// Contains culture specific values for <see cref="IPublishedContent"/>.
/// </summary>
public class PublishedCultureInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="PublishedCultureInfo"/> class.
/// </summary>
public PublishedCultureInfo(string culture, string name, string urlSegment, DateTime date)
{
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentNullOrEmptyException(nameof(culture));
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
Culture = culture;
Name = name;
UrlSegment = urlSegment;
Date = date;
}
/// <summary>
/// Gets the culture.
/// </summary>
public string Culture { get; }
/// <summary>
/// Gets the name of the item.
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the url segment of the item.
/// </summary>
public string UrlSegment { get; }
/// <summary>
/// Gets the date associated with the culture.
/// </summary>
/// <remarks>
/// <para>For published culture, this is the date the culture was published. For draft
/// cultures, this is the date the culture was made available, ie the last time its
/// name changed.</para>
/// </remarks>
public DateTime Date { get; }
}
}

View File

@@ -1,62 +0,0 @@
using System;
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// Represents a published data type.
/// </summary>
/// <remarks>
/// <para>Instances of the <see cref="PublishedDataType"/> class are immutable, ie
/// if the data type changes, then a new class needs to be created.</para>
/// <para>These instances should be created by an <see cref="IPublishedContentTypeFactory"/>.</para>
/// </remarks>
public class PublishedDataType
{
private readonly Lazy<object> _lazyConfiguration;
/// <summary>
/// Initializes a new instance of the <see cref="PublishedDataType"/> class.
/// </summary>
internal PublishedDataType(int id, string editorAlias, Lazy<object> lazyConfiguration)
{
_lazyConfiguration = lazyConfiguration;
Id = id;
EditorAlias = editorAlias;
}
/// <summary>
/// Gets the datatype identifier.
/// </summary>
public int Id { get; }
/// <summary>
/// Gets the data type editor alias.
/// </summary>
public string EditorAlias { get; }
/// <summary>
/// Gets the data type configuration.
/// </summary>
public object Configuration => _lazyConfiguration.Value;
/// <summary>
/// Gets the configuration object.
/// </summary>
/// <typeparam name="T">The expected type of the configuration object.</typeparam>
/// <exception cref="InvalidCastException">When the datatype configuration is not of the expected type.</exception>
public T ConfigurationAs<T>()
where T : class
{
switch (Configuration)
{
case null:
return null;
case T configurationAsT:
return configurationAsT;
}
throw new InvalidCastException($"Cannot cast dataType configuration, of type {Configuration.GetType().Name}, to {typeof(T).Name}.");
}
}
}

View File

@@ -1,34 +0,0 @@
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// The type of published element.
/// </summary>
/// <remarks>Can be a simple element, or a document, a media, a member.</remarks>
public enum PublishedItemType
{
/// <summary>
/// Unknown.
/// </summary>
Unknown = 0,
/// <summary>
/// An element.
/// </summary>
Element,
/// <summary>
/// A document.
/// </summary>
Content,
/// <summary>
/// A media.
/// </summary>
Media,
/// <summary>
/// A member.
/// </summary>
Member
}
}

View File

@@ -1,23 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// Provides a CurrentUICulture-based implementation of <see cref="IVariationContextAccessor"/>.
/// </summary>
/// <remarks>
/// <para>This accessor does not support segments. There is no need to set the current context.</para>
/// </remarks>
public class ThreadCultureVariationContextAccessor : IVariationContextAccessor
{
private readonly ConcurrentDictionary<string, VariationContext> _contexts = new ConcurrentDictionary<string, VariationContext>();
public VariationContext VariationContext
{
get => _contexts.GetOrAdd(Thread.CurrentThread.CurrentUICulture.Name, culture => new VariationContext(culture));
set => throw new NotSupportedException();
}
}
}

View File

@@ -1,27 +0,0 @@
namespace Umbraco.Core.Models.PublishedContent
{
/// <summary>
/// Represents the variation context.
/// </summary>
public class VariationContext
{
/// <summary>
/// Initializes a new instance of the <see cref="VariationContext"/> class.
/// </summary>
public VariationContext(string culture = null, string segment = null)
{
Culture = culture ?? ""; // cannot be null, default to invariant
Segment = segment ?? ""; // cannot be null, default to neutral
}
/// <summary>
/// Gets the culture.
/// </summary>
public string Culture { get; }
/// <summary>
/// Gets the segment.
/// </summary>
public string Segment { get; }
}
}