static void CheckFilterFunc(Type expectedType, Type filterType, MappingSchema mappingSchema) { var propType = expectedType; if (EagerLoading.IsEnumerableType(expectedType, mappingSchema)) { propType = EagerLoading.GetEnumerableElementType(expectedType, mappingSchema); } var itemType = typeof(Expression <>).IsSameOrParentOf(filterType) ? filterType.GetGenericArguments()[0].GetGenericArguments()[0].GetGenericArguments()[0] : filterType.GetGenericArguments()[0].GetGenericArguments()[0]; if (propType != itemType) { throw new LinqException("Invalid filter function usage."); } }
public static Expression EnrichLoadWith(IDataContext dataContext, Expression table, Type entityType, List <LoadWithInfo[]> loadWith, MappingSchema mappingSchema) { var args = new List <Expression>(2); var currentObj = table; foreach (var members in loadWith) { var currentEntityType = entityType; var isPrevEnumerable = false; Type?prevMemberType = null; foreach (var member in members) { args.Clear(); args.Add(currentObj); var memberType = member.MemberInfo.GetMemberType(); var isEnumerableMember = EagerLoading.IsEnumerableType(memberType, mappingSchema); var desiredType = member.MemberInfo.IsMethodEx() ? currentEntityType : member.MemberInfo.DeclaringType; var entityParam = Expression.Parameter(currentEntityType, "e"); var loadBody = desiredType == currentEntityType ? (Expression)entityParam : Expression.Convert(entityParam, desiredType); loadBody = Expression.MakeMemberAccess(loadBody, member.MemberInfo); if (member.MemberFilter != null) { loadBody = member.MemberFilter.GetBody(loadBody); } var hasFilterFunc = member.FilterFunc != null; if (isEnumerableMember && hasFilterFunc) { var propType = EagerLoading.GetEnumerableElementType(memberType, mappingSchema); var enumerableType = typeof(IEnumerable <>).MakeGenericType(propType); if (loadBody.Type != enumerableType) { loadBody = Expression.Convert(loadBody, enumerableType); } } args.Add(Expression.Quote(Expression.Lambda(loadBody, entityParam))); if (hasFilterFunc) { args.Add(member.FilterFunc !); } MethodInfo method; if (prevMemberType == null) { method = !hasFilterFunc ? Methods.LinqToDB.LoadWith : isEnumerableMember ? Methods.LinqToDB.LoadWithManyFilter : Methods.LinqToDB.LoadWithSingleFilter; var propType = memberType; if (hasFilterFunc && isEnumerableMember) { propType = EagerLoading.GetEnumerableElementType(propType, mappingSchema); } method = method.MakeGenericMethod(entityType, propType); } else { if (isPrevEnumerable) { if (!hasFilterFunc) { method = Methods.LinqToDB.ThenLoadFromMany; } else if (isEnumerableMember) { method = Methods.LinqToDB.ThenLoadFromManyManyFilter; } else { method = Methods.LinqToDB.ThenLoadFromManySingleFilter; } } else { if (!hasFilterFunc) { method = Methods.LinqToDB.ThenLoadFromSingle; } else if (isEnumerableMember) { method = Methods.LinqToDB.ThenLoadFromSingleManyFilter; } else { method = Methods.LinqToDB.ThenLoadFromSingleSingleFilter; } } var propType = memberType; if (hasFilterFunc && isEnumerableMember) { propType = EagerLoading.GetEnumerableElementType(propType, mappingSchema); } method = method.MakeGenericMethod(entityType, prevMemberType, propType); } currentObj = Expression.Call(method, args); isPrevEnumerable = isEnumerableMember && !hasFilterFunc; if (isEnumerableMember) { memberType = EagerLoading.GetEnumerableElementType(memberType, mappingSchema); } prevMemberType = memberType; currentEntityType = memberType; } } return(currentObj); }