2014-11-17 13 views
7

Erstens ist dies nicht ein Duplikat von IEnumerable<T> as return type for WCF methods, ich glaube, ich verstehe, dass die WCF-Architektur nur konkrete Typen ermöglicht, die übertragen werden können, die in eine Nachricht gestopft werden können.IEnumerable <T> Semantik mit einem NetTcpBinding WCF-Dienst erhalten?

Zweitens unser Setup jedoch ist nicht ein allgemeiner Service, sondern ein Bündels von proprietären Anwendungen über C# Anschluss von bis + WCF + NetTcpBinding + Protobuf (nur) so können wir mehr Raum für einige Tricks haben, dass etwas, das braucht verbindlich neutral sein.

Drittens ist es weder meine Aufgabe noch diese Frage, ein anderes RPC- oder Messaging-Framework vorzuschlagen.


„IEnumerable Semantik“, für die Zwecke dieser Frage ist:

  • Die zurückgegebene Sequenz beliebig groß sein kann - es ist daher nicht möglich, die Sequenz zu einem List konvertieren o.ä.
  • Es ist nicht im Voraus bekannt, wie viele Artikel
  • Anrufer nur foreach damit fertig und werden können zurückgegeben werden.

In einer lokalen Montage, eine C# Schnittstelle mein sieht wie folgt aus:

interface IStuffProvider { 
    IEnumerable<Stuff> GetItems(); // may open large file or access database 
} 

Sie können nicht direkt an einen WCF-Dienst abzubilden. Etwas, das das gleiche erreichen könnte könnte wie folgt aussehen:

[ServiceContract(SessionMode = SessionMode.Required)] 
interface IStuffService { 
    [OperationContract] 
    void Reset(); // may open large file or access database 
    [OperationContract] 
    List<Stuff> GetNext(); // return next batch of items (empty list if no more available) 
} 

Natürlich IStuffService mit mehr Fehlern anfällig als ein IStuffProvider und fügen Sie in die Mischung als viele Einsatzszenarien würde bedeuten, sowohl Service und Client auf demselben mit Maschine, so für "Benutzer-Code" wäre es nicht sehr wichtig zu wissen, dass "das Netzwerk" beteiligt ist, ist der Benutzer-Code nur an einer einfachen Schnittstelle interessiert.

Eine Option wäre natürlich eine clientseitige Schnittstelle Wrapper-Implementierung, die IStuffProvider exponiert und intern an und verwendet IStuffService. Es scheint jedoch, dass es wirklich wünschenswert wäre, zwei Schnittstellen, eine für Benutzer-Code, eine einzige für die WCF-Kommunikation zu pflegen, vor allem, da diese Anwendungen ohnehin eng miteinander verbunden sind, so dass die zusätzliche Abstraktion scheint nur Overhead.

Welche Möglichkeiten haben wir hier mit WCF?


Beachten Sie, dass nach dem Einschalten der Lektüre auf, die Streamed Binding eine schlechte Lösung scheint, als würde ich noch einen Wrapper müssen auf der Clientseite und die Service-Schnittstelle würde komplizierter für keinen wirklichen Gewinn bekommen in meinem Fall: Ich brauche keine maximale binäre Übertragungseffizienz, ich möchte eine gute Implementierung + Wartungseffizienz.

+5

Vielleicht können Sie die [Streaming-Funktionalität] (http://msdn.microsoft.com/en-us/library/ms733742 (v = vs.110) verwenden. aspx) das ist provi ded von WCF? (Ich habe WCF schon eine Weile nicht benutzt, daher bin ich mir nicht sicher, ob es geeignet ist ...) –

+0

@AasmundEldhuset - sicherlich eine lohnende Lektüre. Es scheint jedoch eine Menge an Strings zu geben. –

+0

WCF neigt dazu, so zu sein, nicht wahr? ;-) –

Antwort

0

Was ich am Ende tat ist haben:

a) Der OO SchnittstelleIStuffProvider wie oben mit dem GetLines() wie oben Mitglied.

b) Der WCF-Service-Schnittstelle (und es ist Implementierung) implementiert ein Zugriffsmuster wie folgt aus:

[OperationContract] 
    ReadToken StartReadingLines(...); 

    [OperationContract] 
    // return next batch of items (empty list if no more available) 
    List<Stuff> ReadNextLines(ReadToken readToken); 

    [OperationContract] 
    void FinishReadingLines(ReadToken readToken); 

c) Der Kunde greift auf den Dienst über eine Proxy-Klasse die IStuffProvider implementiert und bildet einen Aufruf die GetLines() Funktion zu den oben genannten drei Funktionen:

// implementation in the proxy class: 
    public IEnumerable<Stuff> GetLines() 
    { 
     var readToken = _dataService.StartReadingLines(...); 
     try { 
      for (List<Stuff> lines = _dataService.ReadNextLines(readToken); lines.Count > 0; lines = _dataService.ReadNextLines(readToken)) { 
       foreach (var line in lines) { 
        yield return line; 
       } 
      } 
     } finally { 
      _dataService.FinishReadingLines(readToken); 
     } 
    } 
1

Vor einiger Zeit hatten wir in unserem Projekt die gleiche "Einschränkung" für WCF. Um kurz, landeten wir mit

interface IStuffProvider { 
    List<Stuff> GetItems(int page, int pageSize); // may open large file or access database 
} 

Ja, es ist nicht das gleiche wie IEnumerable<Stuff> GetItems(); ist Ja, wir können in Schwierigkeiten bekommen, wenn einige Artikel hinzugefügt/entfernt auf bereits empfangene Seite. Ja, es sind einige serverseitige Optimierungen erforderlich, wenn der Server mit Elementen in Bezug auf IEnumerable<Stuff> arbeitet. Aber es ist immer noch streng typisiert und bringt nicht viel zusätzliche Logik in den Client oder den Server.

+1

"Bitte beachten Sie, es ist keine Antwort auf die Frage, aber einige gemeinsame Gedanken." - Soll das nicht als Kommentar gepostet werden? –

+0

@DarrenYoung nein –

+1

Dies liefert keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klärung zu bitten, hinterlasse einen Kommentar unter seinem Beitrag. –