/// <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); }