using System.Linq.Expressions; using System.Reflection; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Infrastructure.ModelsBuilder; // same namespace as original Umbraco.Web PublishedElementExtensions // ReSharper disable once CheckNamespace namespace Umbraco.Extensions; /// /// Provides extension methods to models. /// public static class PublishedElementExtensions { /// /// Gets the value of a property. /// public static TValue? ValueFor( this TModel model, IPublishedValueFallback publishedValueFallback, Expression> property, string? culture = null, string? segment = null, Fallback fallback = default, TValue? defaultValue = default) where TModel : IPublishedElement { var alias = GetAlias(model, property); return model.Value(publishedValueFallback, alias, culture, segment, fallback, defaultValue); } // TODO: that one should be public so ppl can use it private static string GetAlias(TModel model, Expression> property) { if (property.NodeType != ExpressionType.Lambda) { throw new ArgumentException("Not a proper lambda expression (lambda).", nameof(property)); } var lambda = (LambdaExpression)property; Expression lambdaBody = lambda.Body; if (lambdaBody.NodeType != ExpressionType.MemberAccess) { throw new ArgumentException("Not a proper lambda expression (body).", nameof(property)); } var memberExpression = (MemberExpression)lambdaBody; if (memberExpression.Expression?.NodeType != ExpressionType.Parameter) { throw new ArgumentException("Not a proper lambda expression (member).", nameof(property)); } MemberInfo member = memberExpression.Member; ImplementPropertyTypeAttribute? attribute = member.GetCustomAttribute(); if (attribute == null) { throw new InvalidOperationException("Property is not marked with ImplementPropertyType attribute."); } return attribute.Alias; } }