Asons
Asons

Reputation: 87251

Linq query stored as string and/or serialized as Json

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

Answers (2)

Adrian Iftode
Adrian Iftode

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

Metheny
Metheny

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

Related Questions