Jeremy Choate Jeremy Choate - 19 days ago 5
C# Question

Using WCF Service to Access Data in a Windows Service That's Hosting the WCF Service

I am obviously brand new to WCF and Windows Services.

I have a Windows Service that does nothing but increment an integer variable, every second. I want to write a simple Windows Forms client to display the current value of the variable in a label control, for example.

I've come to believe that the answer to bridging this gap is a WCF Service.

I'm trying to host this WCF Service in the Windows Service, but I have no idea how to link everything together. The WCF Service contains a reference to the Windows Service, so that it can access the value of the integer variable.

However, don't I need to put a reference to the WCF Service in the Windows Service in order to host it? How do I avoid a circular dependency?

I don't necessarily need specific code -- I just need to know if it's possible to do what I'm wanting to do and how to do it, conceptually.

Thanks for any help you can provide!

Answer

I went back and re-wrote everything. I was thoroughly unsatisfied with putting everything in the same assembly, so I went back and redesigned the whole application.

Here is how I finally architected this solution:

I ended up with FIVE projects in this solution (SIX, if you count the console app that I used for testing):

  • Counter Logic - the part of the program that does the actual timing and incrementing
  • WCF Service - the part that bridges the gap between my client(s) and the server
  • Windows Service - the part that hosts the WCF service and my counter logic
  • Windows Forms Client - the front-end that communicates with my Windows Service via WCF
  • Interfaces & Data Contracts - for WCF Operation contracts and data contracts

The projects reference each other in the following way:

  • Counter Logic - references Interfaces & Data Contracts
  • WCF Service - references Interfaces & Data Contracts
  • Windows Service - references Counter Logic, WCF Service, and Interfaces & Data Contracts
  • Windows Forms Client - references Interfaces & Data Contracts
  • Interfaces & Data Contracts - references no other project

The Windows Service provides the hosting environment for the WCF Service and the Counter Logic. The Windows Service needed to reference the WCF Service in order to instantiate it and host it; the WCF Service needed to reference the Windows Service in order to access the integer variable in the Counter Logic.

In order to break this circular dependency, instead of referencing the Windows Service in the WCF Service, I sent a reference to the Counter Logic instance from the Windows Service to the WCF Service, when I created the ServiceHost object:

In the Windows Service project:

protected override void OnStart(string[] args)
{
    if (_serviceHost != null)
    {
        _serviceHost.Close();
    }

    _counterObject = new CounterClass();
    _counterObject.StartCounting();

    _wcfService = new CounterWCFService(_counterObject);

    _serviceHost = new ServiceHost(_wcfService);
    _serviceHost.Open();
}

There is at least one drawback to this scheme, however. In order to pass in the Counter Logic instance as a parameter to the WCF Service, I couldn't use the typical ServiceHost constructor that accepts the typeof the WCF Service. This constructor can only be used when the WCF Service's constructor is parameter-less. Instead, I used the overloaded constructor that accepts an INSTANCE of the WCF Service. This is why I instantiated the WCF Service and passed in the _counterObject as a parameter before passing the WCF Service to the ServiceHost.

This limits us to a WCF Service that is designated as a Singleton (InstanceContextMode = Single). Since there will only be one client accessing my service at any given time, this is acceptable to me, but I will need to investigate other ways to gain access to the instance of the WCF Service that the standard ServiceHost constructor creates if I wish my future applications to be scalable.

This solution works perfectly for me, now, and because of the modularity provided by putting all the various pieces in their own projects, it allowed me to create a console application to host the Counter Logic and WCF Service in for testing, as well.

Before I installed the Windows Service on my machine, I was able to debug everything in the console application so that I only had to install my service, once, and fire it up.