コード例 #1
0
        /// <summary>
        /// If the specified property refers to a static LambdaExpression property, this sets result to that expression with the source
        /// expression supplied as the lambda parameter.
        /// <para/>
        /// Example: i.SomeAggregateExpression
        /// </summary>
        /// <param name="propertyInfo">The property that may or may not contain a LambdaExpression.</param>
        /// <param name="source">The expression that will be given to the LambdaExpression as a parameter.</param>
        /// <param name="result">If successful, represents the body of a LambdaExpression with the source replacing the original LambdaExpression's parameter.</param>
        /// <returns></returns>
        private static bool TryGetExpressionProperty(PropertyInfo propertyInfo, Expression source, out Expression result)
        {
            if (propertyInfo == null)
            {
                throw new InvalidOperationException($"Property on '{source.Type.FullName}' is not valid");
            }
            var propertyTypeInfo = propertyInfo.PropertyType;

            if (!typeof(Expression).GetTypeInfo().IsAssignableFrom(propertyTypeInfo))
            {
                result = null;
                return(false);
            }

            if (!typeof(LambdaExpression).GetTypeInfo().IsAssignableFrom(propertyTypeInfo))
            {
                throw new InvalidOperationException($"Expression properties must return a LambdaExpression. '{propertyInfo.DeclaringType.FullName}.{propertyInfo.Name}'");
            }

            var property = propertyInfo.GetAccessors().FirstOrDefault();

            if (property == null || !property.IsStatic)
            {
                throw new InvalidOperationException($"Expression properties must be static. '{propertyInfo.DeclaringType.FullName}.{propertyInfo.Name}'");
            }

            // j => j.SomeAggregateExpression
            var lambda  = (LambdaExpression)property.Invoke(null, null);
            var changer = new ParamChanger(lambda.Parameters[0], source);

            // i.SomeAggregateExpression
            result = changer.Visit(lambda.Body);
            return(true);
        }