2013-05-11 17 views
13

È possibile ospitare più contratti di assistenza in un servizio WCF? Se é cosi, come? Ho cercato su google e alcuni post dicono che puoi farlo (ma non come) e altri hanno detto che non è possibile.Host di più contratti in un servizio WCF

Quando eseguo il server, ottengo questo errore:

The contract name 'ConsoleAppWcfCommon.IBarService' could not be found in the list of contracts implemented by the service 'ConsoleAppWcfServer.FooService'.

Questo è il mio codice del server:

static void Main(string[] args) 
    { 
     string serviceAddress = "net.tcp://localhost:8088/FooBarService"; 

     // I'm stuck here as I have to pick *one* service 
     ServiceHost selfServiceHost = new ServiceHost(typeof(FooService));    

     // I can add both endpoints here, but this is what gives me the error. 
     selfServiceHost.AddServiceEndpoint(typeof(IFooService), new NetTcpBinding(), serviceAddress); 
     selfServiceHost.AddServiceEndpoint(typeof(IBarService), new NetTcpBinding(), serviceAddress); 

     selfServiceHost.Open(); 
     Console.ReadLine(); 
     selfServiceHost.Close(); 
    } 

e questo è il codice del client:

static void Main(string[] args) 
    { 
     NetTcpBinding netTcpBinding = new NetTcpBinding(); 

     EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8088/FooBarService"); 

     // Call IFooService 
     var channelFactoryFoo = new ChannelFactory<IFooService>(netTcpBinding, endpointAddress); 
     IFooService channelFoo = channelFactoryFoo.CreateChannel(); 
     Debug.WriteLine(channelFoo.FooMethod1()); 

     // Call IBarService 
     var channelFactoryBar = new ChannelFactory<IBarService>(netTcpBinding, endpointAddress); 
     IBarService channelBar = channelFactoryBar.CreateChannel(); 
     Debug.WriteLine(channelBar.BarMethod1()); 
    } 

Il mio obiettivo è di lasciare il cliente effettua una chiamata a Foo (o Bar) e vede solo i metodi disponibili per ciascuno. Nella mia vera applicazione, ho circa 10 entità di dominio con circa quattro operazioni su ciascuna. Sto cercando di non avere un'interfaccia con 40 metodi. E non voglio dover ospitare 10 diversi servizi WCF per farlo.

+3

L'unico modo per farlo è quello di avere un unico servizio ** ** classe di implementazione che implementa ** entrambi ** interfacce in questione . Ce l'hai? Quindi dovresti avere 'FooService di classe pubblica: IFooService, IBarService {....}' –

+1

http://stackoverflow.com/a/334554/352101 – Bolu

+0

@marc_s Non ce l'ho, ma potrei farlo possedere tutto il codice. Nel mio esempio precedente, stai dicendo che il codice del server dovrebbe funzionare così com'è se FooService implementasse entrambe le interfacce? –

risposta

21

Come sottolineato da marc_s, la risposta era quella di avere una classe di implementazione del servizio che implementasse entrambe le interfacce. Di seguito è riportato il codice completo di lavoro.

Server:

static void Main(string[] args) 
    { 
     string serviceAddress = "net.tcp://localhost:8088/FooBarService"; 

     ServiceHost selfServiceHost = new ServiceHost(typeof(FooService));    

     // The endpoints need to share this binding. 
     var binding = new NetTcpBinding(); 

     selfServiceHost.AddServiceEndpoint(typeof(IFooService), binding, serviceAddress); 
     selfServiceHost.AddServiceEndpoint(typeof(IBarService), binding, serviceAddress); 

     selfServiceHost.Open(); 

     Console.WriteLine("The service is ready."); 
     Console.WriteLine("Press any key to terminate service."); 
     Console.WriteLine(); 
     Console.ReadKey(); 

     selfServiceHost.Close(); 
    } 

Cliente:

static void Main(string[] args) 
    { 
     NetTcpBinding netTcpBinding = new NetTcpBinding(); 

     EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8088/FooBarService"); 

     // Call IFooService 
     var channelFactoryFoo = new ChannelFactory<IFooService>(netTcpBinding, endpointAddress); 
     IFooService channelFoo = channelFactoryFoo.CreateChannel(); 
     Console.WriteLine(channelFoo.FooMethod1()); 

     // Call IBarService 
     var channelFactoryBar = new ChannelFactory<IBarService>(netTcpBinding, endpointAddress); 
     IBarService channelBar = channelFactoryBar.CreateChannel(); 
     Console.WriteLine(channelBar.BarMethod1()); 

     Console.ReadKey(); 
    } 

Foo contratto:

[ServiceContract] 
public interface IFooService 
{ 
    [OperationContract] 
    string FooMethod1(); 

    [OperationContract] 
    string FooMethod2(); 
} 

Bar contratto:

[ServiceContract] 
public interface IBarService 
{ 
    [OperationContract] 
    string BarMethod1(); 

    [OperationContract] 
    string BarMethod2(); 
} 

Foo Servizio:

public class FooService : IFooService, IBarService 
{ 
    public string FooMethod1() 
    { 
     return "FooMethod1"; 
    } 

    public string FooMethod2() 
    { 
     return "FooMethod2"; 
    } 

    public string BarMethod1() 
    { 
     return "BarMethod1"; 
    } 

    public string BarMethod2() 
    { 
     return "BarMethod2"; 
    } 
} 
+1

Mi piace molto che tu abbia pubblicato il codice del risultato finale - questo aiuta gli altri, me incluso. Vedo commenti come posterò il codice finale; eppure le persone semplicemente non lo fanno e io sono rimasto a battere la testa! ++ – Stix

+0

Bel codice, ma se sono in WCF ospitato su IIS, dove metto le cose che vanno in Main? – Rhyous

+0

Si troverebbe nell'area del servizio WCF che inizializza le cose all'avvio del servizio. Dove attualmente imposti i binding e gli endpoint? Ecco dove andrebbe questo codice. –

Problemi correlati