public Expression HandleLeave( SelectionVisitorContext context, IFieldSelection selection, Expression expression) { var argumentName = context.SelectionContext.FilterArgumentName; if (context.TryGetValueNode(argumentName, out IValueNode? filter) && selection.Field.Arguments[argumentName].Type is InputObjectType iot && iot is IFilterInputType fit) { var visitorContext = new QueryableFilterVisitorContext( iot, fit.EntityType, context.Conversion, false); QueryableFilterVisitor.Default.Visit(filter, visitorContext); return(Expression.Call( typeof(Enumerable), "Where", new[] { fit.EntityType }, expression, visitorContext.CreateFilter())); } return(expression); }
protected override void Configure(IObjectTypeDescriptor descriptor) { descriptor.ExtendQuery(); descriptor .Field("games") .Type <NonNullType <ListType <NonNullType <GameType> > > >() .Argument("excludeDeleted", arg => arg.Type <BooleanType>() .Description("Exclude games that have been marked as deleted. " + "Setting this to true is shorthand for retrieving games with the game_deleted metadata not set to \"true\".") .DefaultValue(true)) .AddFilterArguments <GameRecordQueryFilterInputType>() .Use(next => context => { IValueNode valueNode = context.ArgumentValue <IValueNode>("where"); bool excludeDeleted = context.ArgumentValue <bool>("excludeDeleted"); Expression <Func <IGameRecordQuery, bool> > excludeDeletedQuery = r => !r.Metadata.Any(r => r.MetadataKey == GameMetadataKeys.Deleted && r.MetadataValue == "true"); var queryBuilder = context.SnowflakeService <IGameLibrary>(); if (valueNode is null || valueNode is NullValueNode) { if (!excludeDeleted) { context.Result = queryBuilder .GetAllGames() .ToList(); } else { context.Result = queryBuilder.QueryGames(excludeDeletedQuery); } return(next.Invoke(context)); } if (context.Field.Arguments["where"].Type is InputObjectType iot && iot is IFilterInputType) { var filter = new QueryableFilterVisitorContext(iot, typeof(IGameRecordQuery), context.GetTypeConverter(), true); QueryableFilterVisitor.Default.Visit(valueNode, filter); var expr = filter.CreateFilter <IGameRecordQuery>(); if (!excludeDeleted) { context.Result = queryBuilder.QueryGames(expr).ToList(); } else { // Invoke works fine here. We could use a expression tree visitor, but // that is a lot more code than just using Invoke. ParameterExpression param = expr.Parameters[0]; var combinedBody = Expression.AndAlso( expr.Body, Expression.Invoke(excludeDeletedQuery, param) ); var combinedLambda = Expression.Lambda <Func <IGameRecordQuery, bool> >(combinedBody, param); context.Result = queryBuilder.QueryGames(combinedLambda).ToList(); } } return(next.Invoke(context)); }) .UsePaging <GameType>(); }