private static ISelect <T1> IncludeLevel <T1>(this ISelect <T1> select, int level, TableRefTree tree, ParameterExpression parameterExpression = null, MemberExpression bodyExpression = null) { var includeMethod = select.GetType().GetMethod("Include"); var includeManyMethod = select.GetType().GetMethod("IncludeMany"); parameterExpression ??= Expression.Parameter(tree.TableInfo.Type, "t"); foreach (var sub in tree.Subs) { switch (sub.TableRef.RefType) { case TableRefType.ManyToOne: case TableRefType.OneToOne: { var body = bodyExpression == null?Expression.Property(parameterExpression, sub.TableRef.Property) : Expression.Property(bodyExpression, sub.TableRef.Property); if (sub.Subs.Count == 0) { var funcType = typeof(Func <,>).MakeGenericType(parameterExpression.Type, sub.TableRef.RefEntityType); var navigateSelector = Expression.Lambda(funcType, body, parameterExpression); includeMethod.MakeGenericMethod(sub.TableRef.RefEntityType).Invoke(select, new object[] { navigateSelector }); } else { select.IncludeLevel(level, sub, parameterExpression, body); } } break; case TableRefType.ManyToMany: case TableRefType.OneToMany: { var body = bodyExpression == null?Expression.Property(parameterExpression, sub.TableRef.Property) : Expression.Property(bodyExpression, sub.TableRef.Property); object then = null; if (sub.Subs.Count > 0) { //var thenSelectType = select.GetType().GetGenericTypeDefinition().MakeGenericType(sub.TableRef.RefEntityType); var thenSelectType = typeof(ISelect <>).MakeGenericType(sub.TableRef.RefEntityType); var thenType = typeof(Action <>).MakeGenericType(thenSelectType); var thenParameter = Expression.Parameter(thenSelectType, "then"); var thenMethod = typeof(FreeSql_1113_Extensions).GetMethod(nameof(IncludeLevel)).MakeGenericMethod(sub.TableRef.RefEntityType); var thenLevelConst = Expression.Constant(level - sub.Level + 1); var thenBody = Expression.Call(null, thenMethod, thenParameter, thenLevelConst); var thenExpression = Expression.Lambda(thenType, thenBody, thenParameter); then = thenExpression.Compile(); } var funcType = typeof(Func <,>).MakeGenericType(parameterExpression.Type, typeof(IEnumerable <>).MakeGenericType(sub.TableRef.RefEntityType)); var navigateSelector = Expression.Lambda(funcType, body, parameterExpression); includeManyMethod.MakeGenericMethod(sub.TableRef.RefEntityType).Invoke(select, new object[] { navigateSelector, then }); } break; } } return(select); }
public static ISelect <T1> IncludeLevel <T1>(this ISelect <T1> select, int level) { var tree = TableRefTree.GetTableRefTree(select, level); return(select.IncludeLevel(level, tree)); }