Запрос Linq хранится в виде строки и / или сериализуется как Json - PullRequest
1 голос
/ 27 апреля 2019

С заданным списком объектов, например

public List<Event> itemList { get; set; }

Мне нравится запрашивать это

var newItemList = itemList
                  .Where(l => l.Published && l.PublishStart <= DateTime.Today)
                  .OrderBy(l => l.PublishStart)
                  .ToList();

Теперь мне нужно иметь возможность иметь несколько запросов и начать с выполнения

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...

Обратите внимание, эти образцы упрощены / сокращены


Поскольку вышесказанное становится все длиннее и длиннее, и, чтобы немного упростить код, можно ли сохранить запрос в виде строки и / или сериализовать как Json и сделать что-то подобное?

    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();

Как уже упоминалось, я понимаю, что он не может быть безопасным с точки зрения типов, тем не менее, мне действительно нужно, чтобы он был упорядочен или сериализован тем или иным образом, поэтому его можно динамически добавлять в решение.

Ответы [ 2 ]

1 голос
/ 27 апреля 2019

Да, вы можете сделать это, используя пакет nuget 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();   

Но, как указали другие, это может не понадобиться, поскольку IEnumerable Интерфейс является составным, так что вы можете решить, что помещать в предложения Where, не выполняя их на самом деле.

    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

Это дублирование может раздражать, поэтому у вас также есть возможность использовать 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 
1 голос
/ 27 апреля 2019

Вы можете сделать это с помощью методов, например:

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...