Skip to content

Instantly share code, notes, and snippets.

@brendanmckenzie
Created April 6, 2019 11:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brendanmckenzie/2b964194229fd36bbe28c5c946d9da80 to your computer and use it in GitHub Desktop.
Save brendanmckenzie/2b964194229fd36bbe28c5c946d9da80 to your computer and use it in GitHub Desktop.
public abstract class ListFilter
{
public string Name { get; set; }
public Type ValueType { get; set; }
public Type ArgumentType { get; set; }
public object DefaultValue { get; set; }
public bool Nullable { get; set; }
public abstract bool Execute(object entity, object value);
}
public class ListFilter<TEntity, TValue> : ListFilter
where TEntity : class
{
public ListFilter()
{
ValueType = typeof(TValue);
}
public ListFilter(string name, TValue defaultValue = default(TValue))
: this()
{
Name = name;
DefaultValue = defaultValue;
}
public Func<TEntity, TValue, bool> Func { get; set; }
public override bool Execute(object entity, object value)
{
return Func.Invoke(entity as TEntity, (TValue)(value ?? DefaultValue));
}
}
public class MyQuery : ObjectGraphType
{
readonly DataContext _dataContext;
public MyQuery(IDependencyResolver resolver)
{
_dataContext = resolver.Resolve<DataContext>();
RegisterCountries();
}
void RegisterCountries()
{
RegisterSingleType<CountryType, Country>("country");
RegisterListType<CountryType, Country>("countries", new ListFilter[]
{
new ListFilter<Country, string>("filter")
{
ArgumentType = typeof(StringGraphType),
Func = (ent, value) => ent.Name.Contains(value, StringComparison.InvariantCultureIgnoreCase)
|| ent.Iso2.Equals(value, StringComparison.InvariantCultureIgnoreCase)
|| ent.Iso3.Equals(value, StringComparison.InvariantCultureIgnoreCase)
}
});
}
void RegisterListType<TSchema, TEntity>(string name, IEnumerable<ListFilter> filters = null, Func<IEnumerable<TEntity>, IEnumerable<TEntity>> orderBy = null)
where TSchema : IGraphType
where TEntity : class
{
filters = filters ?? Enumerable.Empty<ListFilter>();
var arguments = new QueryArgument[]
{
new QueryArgument<IntGraphType> { Name = "take" },
new QueryArgument<IntGraphType> { Name = "skip" },
}.Concat(filters.Select(ent => new QueryArgument(ent.ArgumentType) { Name = ent.Name }));
Field<PaginatedListType<TEntity, TSchema>>(
name,
arguments: new QueryArguments(arguments),
resolve: context => HandleList<TEntity>(context, filters, orderBy));
}
void RegisterSingleType<TSchema, TEntity>(string name)
where TSchema : IGraphType
where TEntity : class
{
Field<TSchema>(
name,
arguments: new QueryArguments(new QueryArgument<IdGraphType> { Name = "id" }),
resolve: HandleSingle<TEntity>);
}
PaginatedList<TEntity> HandleList<TEntity>(ResolveFieldContext<object> context, IEnumerable<ListFilter> filters, Func<IEnumerable<TEntity>, IEnumerable<TEntity>> orderBy)
where TEntity : class
{
var skip = context.GetArgument<int>("skip", 0);
var take = context.GetArgument<int>("take", 10);
var entities = _dataContext.Set<TEntity>().AsEnumerable();
if (orderBy != null)
{
entities = orderBy(entities);
}
foreach (var filter in filters)
{
if (context.HasArgument(filter.Name))
{
var value = context.GetArgument(filter.ValueType, filter.Name);
entities = entities.Where(ent => filter.Execute(ent, value));
}
}
var totalCount = entities.Count();
var results = entities.Skip(skip).Take(take);
return new PaginatedList<TEntity>
{
Items = results,
PageInfo = new PageInfo
{
Skip = skip,
Take = take,
Total = totalCount
}
};
}
async Task<TEntity> HandleSingle<TEntity>(ResolveFieldContext<object> context)
where TEntity : class
{
return await _dataContext.Set<TEntity>().FindAsync(context.GetArgument<Guid>("id"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment