protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var table = sequence as TableBuilder.TableContext; if (table != null && table.InheritanceMapping.Count > 0) { var objectType = methodCall.Type.GetGenericArgumentsEx()[0]; if (table.ObjectType.IsSameOrParentOf(objectType)) { var predicate = builder.MakeIsPredicate(table, objectType); if (!(predicate is IExpr)) { sequence.Select.Where.Search.Conditions.AddLast(new Condition(false, predicate)); } } } else { var toType = methodCall.Type.GetGenericArgumentsEx()[0]; var gargs = methodCall.Arguments[0].Type.GetGenericArguments(typeof(IQueryable <>)); var fromType = gargs == null ? typeof(object) : gargs[0]; if (toType.IsSubclassOfEx(fromType)) { for (var type = toType.BaseTypeEx(); type != null && type != typeof(object); type = type.BaseTypeEx()) { var mapping = builder.MappingSchema.GetEntityDescriptor(type).InheritanceMapping; if (mapping.Count > 0) { var predicate = MakeIsPredicate(builder, sequence, fromType, toType); sequence.Select.Where.Search.Conditions.AddLast(new Condition(false, predicate)); return(new OfTypeContext(sequence, methodCall)); } } } } return(sequence); }
private static ISqlPredicate MakeIsPredicate(ExpressionBuilder builder, IBuildContext context, Type fromType, Type toType) { var table = new SqlTable(builder.MappingSchema, fromType); var mapper = builder.MappingSchema.GetEntityDescriptor(fromType); var discriminators = mapper.InheritanceMapping; return(builder.MakeIsPredicate(context, discriminators, toType, name => { var field = table.Fields.Values.First(f => f.Name == name); var member = field.ColumnDescriptor.MemberInfo; var expr = Expression.MakeMemberAccess(Expression.Parameter(member.DeclaringType, "p"), member); var sql = context.ConvertToSql(expr, 1, ConvertFlags.Field)[0].Sql; return sql; })); }