2009-08-04 11 views
1

Ich habe eine Client-Anwendung, einen Server und einen anderen Client, nennen wir es Drittanbieter. Ich habe eine Callback-Schnittstelle als Teil meines Vertrags, der sowohl von der Drittpartei als auch vom Kunden implementiert wird.Kann ich die WCF-Duplexbindung für die Weiterleitung von Nachrichten verwenden?

Die dritte Partei wird eine Serveroperation (Methode) aufrufen, dann löst der Server einen Rückruf aus, aber anstatt den Rückruf der dritten Partei aufzurufen, ruft er die Callback-Implementierung des Clients auf.

+1

Ich sehe hier keine Frage. –

Antwort

0

Von einem schnellen Lesen der Microsoft Duplex Service-Dokumentation glaube ich nicht, dass das tun wird, was Sie wollen. Es könnte eine andere clevere Kung Fu WCF-Methode geben, aber in meinem Fall habe ich einen "PassThruService" für den Server erstellt, der den gleichen Vertrag wie der echte Dienst implementiert hat und alle erhaltenen Anfragen an den Client gesendet hat.

Dies ist ein Teil meines Codes, der die Stoßrichtung davon erklärt.

0

Ich sehe nicht ganz, was Sie wirklich hier fragen .... aber ich werde versuchen, einige Tipps trotzdem zu geben.

Das Weiterleiten von Nachrichten oder Routing wird in WCF in .NET 3.5 nicht sehr gut unterstützt - die Infrastruktur ist vorhanden, aber es ist immer noch eine Menge Arbeit, sie manuell einzurichten.

Das beste Intro ich in dieses Thema weiß für WCF in .NET 3.5 ist ein zweiteiliger Artikel von Michele Leroux Bustamante auf Magazin MSDN:

Teil 2 hat einen Abschnitt über Duplex-Router - hilft Ihnen das bei Ihrer Suche überhaupt?

WCF in .NET 4.0 verspricht zusätzliche Unterstützung für das Routing - es wird eine RoutingService Basisklasse geben, die zum Schreiben von Routing-Diensten genutzt werden kann und konfigurierbares, Content- oder Metadaten-basiertes Routing ermöglicht ist das, was du brauchst.

.NET 4.0 soll irgendwann später in diesem Jahr (2009) veröffentlicht werden - hoffentlich! Während dies immer noch die Zukunft ist, sieht es rosig aus!

Marc

3

Ja, das können Sie absolut tun.

Der einfachste Weg besteht darin, Ihren Dienst als PerSession-Dienst zu implementieren und den Rückrufkontext bei der Initialisierung/Konstruktion zu erfassen. Normalerweise füge ich das Dienstobjekt (das an diesem Punkt tatsächlich eine Verbindung darstellt) einem internen Kernobjekt hinzu.

Wenn Sie dann eine Nachricht von einem Client erhalten, können Sie ein beliebiges Serviceobjekt (nicht über den Vertrag) anrufen und die Daten intern an den zugehörigen Client weiterleiten.

Dies ist eine ziemlich minimale Implementierung des Konzepts, ohne Ausnahme Handhabung, und einige ziemlich schlechtes Design (statische Klasse BAD!). Ich habe das nicht getestet, aber die Prinzipien sollten auch dann gelten, wenn ich es versäumt habe, ein i zu kreuzen oder ein t zu punktieren. In diesem Beispiel werden auch die Aufrufe an alle Clients weitergeleitet, aber das Auswählen eines einzelnen Clients folgt demselben Grundmuster.

Der Versuch, dies mit einem Singleton-Dienst zu tun, wird schwieriger sein, und ein per-Call-Service wird natürlich nicht funktionieren :)

[ServiceContract(CallbackContract = typeof(ICallback))] 
public interface IContract 
{ 
    [OperationContract(IsOneWay = true)] 
    void SendTheData(string s); 
} 

public interface ICallback 
{ 
    [OperationContract(IsOneWay = true)] 
    void ForwardTheData(string s); 
} 

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.PerSession)] 
public class ServiceConnection : IContract 
{ 
    private ICallback m_callback; 

    public ServiceConnection() 
    { 
     m_callback = OperationContext.Current.GetCallbackChannel<ICallback>(); 
     ServiceCore.Add(this); 
    } 

    public void SendTheData(string s) 
    { 
     ServiceCore.DataArrived(s); 
    } 

    public void SendToClient(string s) 
    { 
     m_callback.ForwardTheData(s); 
    } 
} 

static public class ServiceCore 
{ 
    static private List<ServiceConnection> m_connections = new List<ServiceConnection>(); 


    public static void DataArrived(string s) 
    { 
     foreach(ServiceConnection conn in m_connections) 
     { 
      conn.SendTheData(s); 
     } 
    } 

    public static void Add(ServiceConnection connection) 
    { 
     m_connections.Add(connection); 
    } 
}