Reputation: 87251
With a given list of objects, e.g.
public List<Event> itemList { get; set; }
I do like this to query it
var newItemList = itemList
.Where(l => l.Published && l.PublishStart <= DateTime.Today)
.OrderBy(l => l.PublishStart)
.ToList();
Now I need to be able to have multiple query's and started out with doing
List<Event> newItemList;
if (EventType.Equals("consert"))
{
newItemList = itemList
.Where(l => l.Published && l.PublishType == EventType.Consert)
.OrderBy(l => l.PublishStart)
.ToList();
}
else if (EventType.Equals("last-chance"))
{
newItemList = itemList
.Where(l => l.Published)
.OrderBy(l => l.PublishEnd)
.ToList();
}
// and so on...
Do note, these samples is simplified/shortened
As the above gets longer and longer, and to simplify the code a little, is it possible to store a query as string and/or serialized as Json, and do something like this ?
var query_where = "l => l.Published && l.PublishType == EventType.Consert";
var query_orderby = "l => l.PublishStart";
newItemList = itemList
.Where(query_where)
.OrderBy(query_orderby)
.ToList();
As mentioned, I realize it might not be type-safe, still, I really need it stringified, or serialized, in one way or the other, so it can be dynamically added to the solution.
Upvotes: 1
Views: 326
Reputation: 15673
Yes, you can do it using a nuget package System.Dynamic.Linq.Core
var where = "";
var ordering = "";
if (eventType.Equals("consert"))
{
where = "Published and PublishType =\"Consert\"";
ordering = "PublishStart";
}
else if (eventType.Equals("last-chance"))
{
where = "Published";
ordering = "PublishEnd";
}
newItemList = itemList.AsQueryable() // this is in order to enable Dynamic.Linq
.Where(where)
.OrderBy(ordering)
.ToList();
But as others pointed, you might not need this, since the IEnumerable
interface is composable, in the way that you can decide what put in the Where clauses without actually running them.
IEnumerable<Event> newItems = itemList;
if (eventType.Equals("consert"))
{
newItems = newItems.Where(c => c.Published && c.PublishType == EventType.Consert);
}
else if (eventType.Equals("last-chance"))
{
newItems = newItems.Where(c => c.Published);
}
if (eventType.Equals("consert"))
{
newItems = newItems.OrderBy(c => c.PublishStart);
}
else if (eventType.Equals("last-chance"))
{
newItems = newItems.OrderBy(c => c.PublishEnd);
}
var newItemsList = newItems.ToList(); // newItems holds references to the expressions and the .ToList() call will parse and execute them at this moment
This duplication might be annoying thus you have also the option to use Func
.
IEnumerable<Event> newItems = itemList;
Func<Event, DateTime> orderBy = null;
if (eventType.Equals("consert"))
{
newItems = newItems.Where(c => c.Published && c.PublishType == EventType.Consert);
orderBy = c => c.PublishStart;
}
else if (eventType.Equals("last-chance"))
{
newItems = newItems.Where(c => c.Published);
orderBy = c => c.PublishEnd;
}
if (orderBy != null)
{
newItems = newItems.OrderBy(orderBy);
}
var newItemsList = newItems.ToList(); // newItems holds references to the expressions and the .ToList() call will parse and execute them at this moment
Upvotes: 1
Reputation: 1192
You can do it with methods, for example:
private bool IsEventPublishedConcert(Event l) => l.Published && l.PublishType == EventType.Consert;
private DateTime GetEventStartTime(Event l) => l.StartTime;
newItemList = itemList
.Where(IsEventPublishedConcert)
.OrderBy(GetEventStartTime)
.ToList();
Upvotes: 1