tags:

views:

486

answers:

2

I'm modifying the code in this tutorial to build some basic subscribe push wcf client/server classes, and I've just hit a bit of a brick wall.

The server class in the tutorial is created using the following code:

class Program
  {
    static void Main(string[] args)
    {
      using (ServiceHost host = new ServiceHost(
        typeof(StringReverser),
        new Uri[]{
          new Uri("net.pipe://localhost")
        }))
      {

        host.AddServiceEndpoint(typeof(IStringReverser),
          new NetNamedPipeBinding(),
          "PipeReverse");

        host.Open();

        Console.WriteLine("Service is available. " +
          "Press <ENTER> to exit.");
        Console.ReadLine();

        host.Close();
      }
    }
  }

Which I assume publishes an instance of StringReverser my problem is I need a reference to that instance so I can call a method on it to push data back to the client.

In the tutorial the server just replies to the client using a callback method, instead I'm storing a reference to the client in a list of subscribers. When I need to push data back to the clients I need a reference to the Service object so I can actually utilize do the callback.

Is there a way to publish a Service using WCF that lets you have a reference to the service object? or can I get a reference to the service object from the host object?

Any help would be appreciated...

A: 

Hi, in your servicecontract you can call

OperationContext.Current.GetCallbackChannel());

in any method that is called after the service connects, and then pass it out of the service contract. I typically have a join method where I get a guid for the client and grab the callback there. This is harder than it seems. You either need a singleton/global variable to get it out (easy), or you need to make it so that WCF can use parameterized constructors (hard). For the latter, more correct way of doing it, you need to roll your own classes that implement IInstanceProvider and IEndPointBehavior and add your behavior to the endpoint you are interested in. This has the added benefit of allowing you to use different constructors with different endpoints without redefining your contract. There is unfortunately no typesafe way to do this as you will have to use reflection. Sorry I can't provide a sample, but everything I have is proprietary.

Steve
Thanks but doesn't that get me a reference to client not the server, I need a reference to the StringReverser I just created in program.cs not the client object that called the service.
Omar Kooheji
Sorry, you can pass the stringreverser in as a constructor parameter. If you go the way of the accepted answer, you can only have a single instance of your class used by WCF. This will affect your concurrency model and performance.
Steve
+1  A: 

You can use the singleton pattern in your StringReverser class and pass the instance of it to the ServiceHost constructor:

ServiceHost host = new ServiceHost(
  StringReverser.Instance,
  new Uri[]{new Uri("net.pipe://localhost")}
);
Julien Poulin
rather than passing a singleton can I just create an instance of StringReverser and pass that in.
Omar Kooheji
This looks like the best solution.
Omar Kooheji