views:

235

answers:

2

Context:

I need to develop a monitoring server that monitors some of our applications (these applications are in c#). So I decided to develop the system with WCF which seems suitable for my needs.

These applications must register themselves to the monitoring server when they start. After that the monitoring server can call the methods Start or Stop of these applications.

Everything is completely executed on the same machine, nothing needs to be executed remotely.

So I developed a good prototype and everything works fine. Each application registers itself to the monitoring server.

Question:

ApplicationRegistrationService (see the code below) is the implementation of the monitoring service and it is a singleton instance due to the ServiceBehavior attribute.

Here my problem: I want to access the content of ApplicationRegistrationService per example, the number of connected applications from my server (ConsoleMonitoringServer in the example). But, I am not sure how to achieve this.

Do I need to create a channel in my server to the service like I did in my clients (ConsoleClient) or it exists a better way to achieve this?

Code:

The code is very simplified for the purpose of this question:

//The callback contract interface
public interface IApplicationAction
{
    [OperationContract(IsOneWay = true)]
    void Stop();

    [OperationContract(IsOneWay = true)]
    void Start();
}

[ServiceContract(SessionMode = SessionMode.Required, 
    CallbackContract = typeof(IApplicationAction))]
public interface IApplicationRegistration
{
    [OperationContract]
    void Register(Guid guid, string name);

    [OperationContract]
    void Unregister(Guid guid);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, 
    ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ApplicationRegistrationService : IApplicationRegistration
{
    //IApplicationRegistration Implementation
}

public class ApplicationAction : IApplicationAction
{
    //IApplicationAction Implementation
}

Console application for this example

class ConsoleClient
{
    static void Main(string[] args)
    {
     ApplicationAction actions = new ApplicationAction();

     DuplexChannelFactory<IApplicationRegistration> appRegPipeFactory =
      new DuplexChannelFactory<IApplicationRegistration>(actions,
      new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/AppReg"));

     IApplicationRegistration proxy = appRegPipeFactory.CreateChannel();
     proxy.Register(Guid.Empty, "ThisClientName");

     //Do stuffs
    }
}

Console server for this example

class ConsoleMonitoringServer
{
    static void Main(string[] args)
    {
     using (ServiceHost host = new ServiceHost(typeof(ApplicationRegistrationService),
      new Uri[]{ new Uri("net.pipe://localhost")}))
     {
      host.AddServiceEndpoint(typeof(IApplicationRegistration), 
       new NetNamedPipeBinding(), "AppReg");

      host.Open();

      //Wait until some write something in the console
      Console.ReadLine();

      host.Close();
     }
    }
}
A: 

If you mean you'd like two way communication between your monitoring service and your registered services or nodes, then you probably should be using two way communication in WCF also known as duplex communication. Very cool stuff.

http://www.codeproject.com/KB/WCF/WCF_Duplex_UI_Threads.aspx

Khalid Abuhakmeh
Thanks for the links but I already do a similar thing in my code.
Francis B.
+1  A: 

Finally, I find the answer and it was pretty easy. I just need to create the service instance and pass the reference to the constructor of ServiceHost.

So I need to replace the following code:

using (ServiceHost host = new ServiceHost(typeof(ApplicationRegistrationService),
                new Uri[]{ new Uri("net.pipe://localhost")}))

by :

ApplicationRegistrationService myService = new ApplicationRegistrationService();

using (ServiceHost host = new ServiceHost(myService,
                new Uri[]{ new Uri("net.pipe://localhost")}))
Francis B.