これは、実際にはLadislavMrnkaへの最後のコメントに対する回答です。あなたは言う:
なるほど、「無料のドーナツ」はありません。LINQ to Anyでは、このような動作がありますが、サービスの境界を越える必要があります。つまり、データを(逆)シリアル化する必要があります。
無料ではありませんが、それでも可能です!
サーバー側では、リクエストを初期化するメソッドと結果を取得するメソッドを1つずつ提供する必要があります。
クライアント側(特に低レベルのインフラストラクチャクラスの1つ)では、列挙子でラップでき、最後に、「ビジネス」クラスは他のクラスと同じようにその列挙子を使用できます。
各アイテムに必要な要求/応答の手段で追加のオーバーヘッドが発生することについては、すでに説明しました。これにより、遅延が発生し、ネットワーク負荷が増加します。
疑似RESTfulAPIを使用したこのアプローチのサンプルは、次のようになります。
サーバ側:
POST http://server/api/search-specification
:
本文には、検索に必要なパラメータ(開始日や終了日など)が含まれます
。応答は、検索仕様を識別するURIになります。
GET http://server/api/search-specification/1/next-result
:
回答は次の項目になります。
このためのコントローラーは次のようになります。
public Response PostSearchSpecification(SearchSpecification spec)
{
int id = _searches.Max(x => x.Key) + 1; // Make thread-safe
_searches[id] = _provider.GetSome().GetEnumerator();
return ...;
}
public Item GetNextResult(int searchSpecId)
{
if(_searches[searchSpecId].MoveNext())
return _searches.Current;
else
return null; // or return a HTTP status code that tells the
// client that there are no more items.
}
確かに1つのように見えるので、これを疑似RESTful APIと呼んでいますが、遅延実行を有効にするには、仕様ごとに内部的に状態を保持する必要があります。さらにGET http://server/api/search-specification/1/next-result
、べき等ではありません。
しかし、私はそれが私が意味することを示していると思います:)
クライアント側は、次のようにカプセル化します。
class Search
{
public IEnumerable<Item> Start(params)
{
var client = new HttpClient(...);
var resultsUri = client.Post(new SearchSpecification(params)).Response;
Item item = client.Get<Item>(resultsUri);
while(item != null)
{
yield return item;
item = client.Get<Item>(resultsUri);
}
}
}
そして、あなたはそれをこのように使うでしょう:
var search = new Search();
foreach(var item in search.Start(...))
// ...
このようなものを実装する方法についての生のスケッチです。