Exemple #1
0
 /// <summary>
 /// Validates, creates and compiles the property expression; whilst also determinig the property friendly <see cref="PropertyExpression{TEntity, TProperty}.Text"/>.
 /// </summary>
 /// <param name="propertyExpression">The <see cref="Expression"/> to reference the entity property.</param>
 /// <param name="probeForJsonRefDataSidProperties">Indicates whether to probe for the <see cref="JsonPropertyAttribute"/> via alternate <c>Sid</c> or <c>Sids</c> properties as implemented for reference data.</param>
 /// <returns>A <see cref="PropertyExpression{TEntity, TProperty}"/> which contains (in order) the compiled <see cref="System.Func{TEntity, TProperty}"/>, member name and resulting property text.</returns>
 public static PropertyExpression <TEntity, TProperty> Create <TEntity, TProperty>(Expression <Func <TEntity, TProperty> > propertyExpression, bool probeForJsonRefDataSidProperties = false)
 {
     return(PropertyExpression <TEntity, TProperty> .CreateInternal(Check.NotNull(propertyExpression, nameof(propertyExpression)), probeForJsonRefDataSidProperties));
 }
Exemple #2
0
        /// <summary>
        /// Validates, creates and compiles the property expression; whilst also determinig the property friendly <see cref="Text"/>.
        /// </summary>
        /// <param name="propertyExpression">The <see cref="Expression"/> to reference the entity property.</param>
        /// <param name="probeForJsonRefDataSidProperties">Indicates whether to probe for the <see cref="T:JsonPropertyAttribute"/> via alternate <c>Sid</c> or <c>Sids</c> properties as implemented for reference data.</param>
        /// <returns>A <see cref="PropertyExpression{TEntity, TProperty}"/> which contains (in order) the compiled <see cref="System.Func{TEntity, TProperty}"/>, member name and resulting property text.</returns>
        public static PropertyExpression <TEntity, TProperty> Create(Expression <Func <TEntity, TProperty> > propertyExpression, bool probeForJsonRefDataSidProperties = false)
        {
            if (propertyExpression == null)
            {
                throw new ArgumentNullException("propertyExpression");
            }

            if (propertyExpression.Body.NodeType != ExpressionType.MemberAccess)
            {
                throw new InvalidOperationException("Only Member access expressions are supported.");
            }

            var me = (MemberExpression)propertyExpression.Body;

            // Check cache and reuse as this is an expensive operation.
            var key = new ExpressionKey {
                Type = me.Member.DeclaringType, Name = me.Member.Name, ProbeForJsonRefDataSidProperties = probeForJsonRefDataSidProperties
            };

            if (_expressions.ContainsKey(key))
            {
                return(_expressions[key]);
            }

            if (me.Member.MemberType != MemberTypes.Property)
            {
                throw new InvalidOperationException("Expression results in a Member that is not a Property.");
            }

            if (!me.Member.DeclaringType.GetTypeInfo().IsAssignableFrom(typeof(TEntity).GetTypeInfo()))
            {
                throw new InvalidOperationException("Expression results in a Member for a different Entity class.");
            }

            var pe = new PropertyExpression <TEntity, TProperty>()
            {
                Name = me.Member.Name
            };

            // Either get the friendly text from a corresponding DisplayTextAttribute or split the PascalCase member name into friendlier sentence case text.
            DisplayAttribute ca = me.Member.GetCustomAttribute <DisplayAttribute>(true);

            pe.Text = ca == null?Beef.CodeGen.CodeGenerator.ToSentenceCase(pe.Name) : ca.Name;

            // Get the JSON property name.
            JsonPropertyAttribute jpa = me.Member.GetCustomAttribute <JsonPropertyAttribute>(true);

            if (jpa == null && probeForJsonRefDataSidProperties)
            {
                // Probe corresponding Sid or Sids properties for value (using the standardised naming convention).
                var pi = me.Member.DeclaringType.GetProperty($"{pe.Name}Sid");
                if (pi == null)
                {
                    pi = me.Member.DeclaringType.GetProperty($"{pe.Name}Sids");
                }

                if (pi != null)
                {
                    jpa = pi.GetCustomAttribute <JsonPropertyAttribute>(true);
                }
            }

            pe.JsonPropertyAttribute = jpa;
            pe.JsonName = jpa == null ? pe.Name : jpa.PropertyName;

            // Compile the expression.
            pe._func = propertyExpression.Compile();

            // Recheck cache and use/update accordingly.
            lock (_lock)
            {
                if (_expressions.ContainsKey(key))
                {
                    return(_expressions[key]);
                }

                _expressions.Add(key, pe);
            }

            return(pe);
        }