【问题标题】:How can I extend IEnumerable<T> to load my collection from a web service?如何扩展 IEnumerable<T> 以从 Web 服务加载我的集合?
【发布时间】:2013-12-09 16:48:51
【问题描述】:

我一直在想知道如何实现Enumerable&lt;T&gt;/IEnumerator&lt;T&gt; 以满足以下条件:

  1. 我调用 Web 服务来创建查询
  2. 我轮询 Web 服务以了解它何时准备好返回结果
  3. 一旦 Web 服务准备好返回结果,我就会调用一个方法(例如 GetNext(n))从中获取 n 个项目
  4. 一旦GetNext(n) 返回的结果少于 n 个,我就检索到了我的所有项目。

我在试图弄清楚如何让 IEnumerable 处理我的所有繁重工作时遇到了一些困难,而 MSDN IEnumerable 文档没有帮助。

这是我的代码的简化版本:

public class MyEnumerable : IEnumerable
{
    private MyWebService _service;
    private int _queryID;

    public MyEnumerable(MyWebService service, int queryID)
    {
        _service = service;
        _queryID = queryID;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return new MyEnumerator(_service, _query);
    }
}

public class MyEnumerator : IEnumerator
{
    private List<QueryResult> _items;  //want to load my items from WebService into this
    private MyWebService _service;
    private int _queryID;
    private int _index = 0;

    private MyEnumerator(MyWebService service, int queryID)
    {
        _service = service;
        _queryID = queryID;
    }

    public object Current
    {
        //what goes here? 
    }

    public bool MoveNext()
    {
        //what goes here? would I call the web service here?
    }

    public void Reset()
    {
        _index = 0;
    }

}

希望这更有意义。假设我可以在我的网络服务上调用一个名为 GetNext(n) 的方法。

【问题讨论】:

  • 您不应该通过轮询网络服务来了解它何时有结果,而应该通过某种回调来通知您。
  • lazyberezovsky - 我尝试实现 IEnumerable 和 IEnumerator 并使用我的自定义 Enumerator 来执行 Web 服务逻辑,但我无法弄清楚如何正确编写枚举器(而且我的代码没有'不编译)。
  • @MailmanOdd 然后向我们展示您尝试过的内容,或者可以演示问题的简化版本,并具体说明您遇到的问题。
  • @MailmanOdd 向我们展示您的代码以及您遇到什么异常
  • 对于这样的数据流,我想我会研究 Rx 的 IObservables。 Enumerables 更接近于数组,围绕数据存储而设计,而 Observables 则基于可能随时出现的数据。

标签: c# .net ienumerable ienumerator


【解决方案1】:

除非您有理由不这样做,否则您通常应该使用迭代器块来创建此类序列,而不是显式地实现接口。它将处理样板代码,只留下有趣的实现。像这样的问题通常看起来是这样的:

//you can make this private if you want
public static IEnumerable<IList<Foo>> GetPages(int pageSize)
{
    IList<Foo> nextGroup = ExecuteQuery();
    while (nextGroup.Count == pageSize)
    {
        yield return nextGroup;
        nextGroup = ExecuteQuery();
    }
    if (nextGroup.Any())
        yield return nextGroup;
}

然后您可以使用SelectMany 将组列表展平为单个项目的列表:

public static IEnumerable<Foo> GetItems(int pageSize)
{
    return GetPages(pageSize).SelectMany(x => x);
}

【讨论】:

  • 嗯,我喜欢这个主意。它使这变得简单得多。我想我会以这种方式实现它并将其添加到我的 WebService 消费者类中。谢谢。
【解决方案2】:

使用 Rx Reactive Extensions 和 Buffer 扩展方法。 (意思是 IObservable 而不是 IEnumberable)。似乎与您的用例完美匹配!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多