using System.Linq.Expressions; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Extensions; namespace Umbraco.Cms.Infrastructure.ModelsBuilder; /// /// This is called from within the generated model classes /// /// /// DO NOT REMOVE - although there are not code references this is used directly by the generated models. /// public static class PublishedModelUtility { // looks safer but probably useless... ppl should not call these methods directly // and if they do... they have to take care about not doing stupid things // public static PublishedPropertyType GetModelPropertyType2(Expression> selector) // where T : PublishedContentModel // { // var type = typeof (T); // var s1 = type.GetField("ModelTypeAlias", BindingFlags.Public | BindingFlags.Static); // var alias = (s1.IsLiteral && s1.IsInitOnly && s1.FieldType == typeof(string)) ? (string)s1.GetValue(null) : null; // var s2 = type.GetField("ModelItemType", BindingFlags.Public | BindingFlags.Static); // var itemType = (s2.IsLiteral && s2.IsInitOnly && s2.FieldType == typeof(PublishedItemType)) ? (PublishedItemType)s2.GetValue(null) : 0; // var contentType = PublishedContentType.Get(itemType, alias); // // etc... // } public static IPublishedContentType? GetModelContentType( IPublishedContentTypeCache contentTypeCache, PublishedItemType itemType, string alias) { switch (itemType) { case PublishedItemType.Content: return contentTypeCache.Get(PublishedItemType.Content, alias); case PublishedItemType.Element: return contentTypeCache.Get(PublishedItemType.Element, alias); case PublishedItemType.Media: return contentTypeCache.Get(PublishedItemType.Media, alias); case PublishedItemType.Member: return contentTypeCache.Get(PublishedItemType.Member, alias); default: throw new ArgumentOutOfRangeException(nameof(itemType)); } } public static IPublishedPropertyType? GetModelPropertyType( IPublishedContentType contentType, Expression> selector) // where TModel : PublishedContentModel // TODO: PublishedContentModel _or_ PublishedElementModel { // TODO therefore, missing a check on TModel here if (selector.Body is not MemberExpression expr) { throw new ArgumentException("Not a property expression.", nameof(selector)); } // there _is_ a risk that contentType and T do not match // see note above : accepted risk... ImplementPropertyTypeAttribute? attr = expr.Member .GetCustomAttributes(typeof(ImplementPropertyTypeAttribute), false) .OfType() .SingleOrDefault(); if (string.IsNullOrWhiteSpace(attr?.Alias)) { throw new InvalidOperationException( $"Could not figure out property alias for property \"{expr.Member.Name}\"."); } return contentType.GetPropertyType(attr.Alias); } }