2

绝对是 LINQ 新手,但对 SQL 和 C# 非常有经验,想知道这在 LINQ 中是否可行。如果是这样,我可以在其他地方使用它,但我认为这将是一个很好的起点(并有助于简化/清理一些代码)。这可以更概括,但我认为这可能是一个很好的现实生活示例,可以帮助解释。

背景简介:我正在做一个个人学习项目,构建一个调度程序并学习 Spring.NET/DI、Fluent NHibernate、Quartz.NET,并试图通过 TDD 实现我的壮举。到目前为止学到了很多。

Quartz.NET IScheduler 对象具有这些属性(1)/方法(2)(假设是公共的)...

string[] JobGroupNames { get; }
string[] GetJobNames(string groupName)
Trigger[] GetTriggersOfJob(string jobName, string groupName)

假设触发器定义只是......

class Trigger
{  
    string Name { get; }
}  

我有一个类,我正在尝试获取一个列表,该列表具有如下构造函数(因为它一旦创建就不可变)...

class QuartzJob
{
    public QuartzJob(Guid groupId, Guid jobId, IEnumerable<string> triggerNames)
}

目前这就是我的处理方式......

public IEnumerable<QuartzJob> GetQuartzInfo(IScheduler scheduler)
{
    List<QuartzJob> list = new List<QuartzJob>();

    foreach (string grp in scheduler.JobGroupNames)
    {
        foreach (string job in scheduler.GetJobNames(grp))
        {
            var triggerNames = scheduler
                .GetTriggersOfJob(job, grp)
                .ToList()
                .ConvertAll(t => t.Name);

            var qj = new QuartzJob(new Guid(grp), new Guid(job), triggerNames);
            list.Add(qj);
        }
    }    
    return list;
}

这种方式工作得很好(虽然可能有点慢和复杂),但是那些双 foreach 循环让我很烦恼,因为我是一个“学习 LINQ”的人,我认为这是一个很好的机会并尝试应用它。

不要求有人为我编写代码,因为这是一个学习项目(虽然你更欢迎你),只是想看看 LINQ 是否可以做这样的事情,如果可以,寻找更多关于它的信息... 使用查询值调用方法,并使用这些值构建另一个查询。如果是这样,它将减少我在代码中其他地方的多个 foreach 循环中的一些。

谢谢!

4

1 回答 1

5

在 LINQ 中执行此操作的关键是要了解 .Select 是您的朋友——但可能会打击您的脾气暴躁的朋友。我小子。您可以使用 Select 和它的表亲 SelectMany 来动态转换您的数组。

public IEnumerable<QuartzJob> GetQuartzInfo(IScheduler scheduler)
{
    IEnumerable<QuartzJob> jobs = scheduler.JobGroupNames.SelectMany(   // Using SelectMany because there is an IEnumerable<QuartzJob> for each group and we want to flatten that.
        groupName => scheduler.GetJobNames(groupName).Select(  // Returns an IEnumerable<QuartzJob> for each group name found.
            jobName => 
                // We're doing a lot in this new but essentially it creates a new QuartzJob for each jobName/groupName combo
                new QuartzJob(new Guid(groupName), new Guid(jobName),
                    scheduler.GetTriggersOfJob(jobName, groupName).Select(trigger => trigger.Name)  // This transforms the GetTriggersOfJob into an IEnumerable<string> for use in the constructor of QuartzJob
                    ))); 
    return new List<QuartzJob>(jobs);
}

或者,如果您更喜欢内联查询语言,它会更具可读性,如下所示:

public IEnumerable<QuartzJob> GetQuartzInfo(IScheduler scheduler)
{
    IEnumerable<QuartzJob> jobs = from groupName in scheduler.JobGroupNames
                                  from jobName in scheduler.GetJobNames(groupName) // stacking the two froms is the equivalent of SelectMany because the first select is defaulted as the result of the second.
                                  select new QuartzJob(new Guid(groupName), new Guid(jobName),
                                      // this sub-select is to get just the IEnumerable<string> of trigger names needed for the constructor.
                                      (from trigger in scheduler.GetTriggersOfJob(jobName, groupName)
                                       select trigger.Name));
    return new List<QuartzJob>(jobs);
}
于 2009-11-24T00:38:43.590 回答