Linq 查询存储为字符串 and/or 序列化为 Json

Linq query stored as string and/or serialized as Json

使用给定的对象列表,例如

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

请注意,这些示例是 simplified/shortened


随着上面越来越长,为了稍微简化代码,是否可以将查询存储为字符串 and/or 序列化为 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();

如前所述,我意识到它可能不是类型安全的,但我确实需要以某种方式将其字符串化或序列化,以便可以将其动态添加到解决方案中。

可以通过方法来实现,例如:

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

是的,您可以使用 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