Sie sind auf Seite 1von 6

Platforms, Frameworks & Libraries Windows Communication Foundation General

WCF Implementation of the Publisher/Subscriber Model


By chakkaradeepcc | 9 Jan 2008
WinXP Vista C#1.0 C#2.0 C#3.0 C# Windows WCF Intermediate

Licence First Posted Views Downloads Bookmarked

CPOL 9 Jan 2008 51,921 1,035 70 times

Implementation of the Publisher and Subscriber model.


4.50 (12 votes)

Download source - 46.6 KB

Introduction
The Publisher/Subscriber model is where the Subscriber is the service to which all clients subscribe and the Publisher is the service which sends messages to all clients who have subscribed to the Subscriber service. That is, suppose we have 10 clients and all 10 clients would subscribe to the Subscriber service to receive notifications (client programs are individual programs), and then whenever the required event occurs, the Publisher notifies all those clients registered.

Background
After a thorough reading done here, I understood how the Publisher/Subscriber model is implemented. To know more about this model, have a look here. The reading should let you understand this model. Then, I went on exploring the Windows Vista SDK, where I found the List Publisher/Subscribe sample. Exploring the same, I was able to understand the logic.

Here is a pictorial representation:

To explain briefly: We have a WCF Service (the above diagram tells that the WCF Service is hosted in IIS) Design the callback contract between the Service and the Client Setup a Delegate and Event, and the delegate method handler is going to raise that particular event So, when clients subscribe, we increment the event handler which would point to the clients callback function Now, we build a separate datasource which implements the service callback contract This datasource is responsible to call the Publish function The Publish function is just going to raise the event, and thus every callback in the Event will be called now

Using the code


I have mainly built three components: PubSubService PubSubClient Publisher
PubSubService

This is our main Service which allows the Client to Subscribe, Unsubscribe, and the Publisher to Publish messages to the subscribed clients. Our Service also has a CallBackContract which is going to be our source at the Client for notifications sent out by the Service. Below is our ServiceContract interface:
[ServiceContract(Namespace = http://ListPublishSubscribe.Service, SessionMode = SessionMode.Required, CallbackContract = typeof (IPubSubContract))] public interface IPubSubService { [OperationContract(IsOneWay = false, IsInitiating=true)] void Subscribe(); [OperationContract(IsOneWay = false, IsInitiating=true)] void Unsubscribe(); [OperationContract(IsOneWay = false)] void PublishNameChange(string Name); }

It is pretty clear what we have. Our ServiceContract SessionType is set to be SessionMode.Required; so, you have to connect the client, and a session is required and it has three OperationContracts namely:

Subscribe UnSubscribe PublishNameChange


The IsOneWay tells that it's not a one way contract, and it's a two way contract meaning that this contract can be called by the Client as well as return some values back to the Client. IsInitiating tells that this contract can initiate a session in the Server/Service. We have specified the interface IPubSubContract as our CallbackContract. This means that this would be a medium of data exchange between the Service and Client, and using these Callbacks, we can actually make the Service notify the Clients regarding specific events. Below is our IPubSubContract interface:
public interface IPubSubContract { [OperationContract(IsOneWay = true)] void NameChange(string Name); }

We just have one OperationContract called NameChange. We would be going into this soon. As now we have our Interfaces defined, it is time to implement our ServiceContract, and below is the class which implements the above IPubSubService interface.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] public class PubSubService : IPubSubService { public delegate void NameChangeEventHandler(object sender, ServiceEventArgs e); public static event NameChangeEventHandler NameChangeEvent; IPubSubContract ServiceCallback = null; NameChangeEventHandler NameHandler = null; public void Subscribe() { ServiceCallback = OperationContext.Current.GetCallbackChannel<IPubSubContract>(); NameHandler = new NameChangeEventHandler(PublishNameChangeHandler); NameChangeEvent += NameHandler; } public void Unsubscribe() { NameChangeEvent -= NameHandler; } public void PublishNameChange(string Name) { ServiceEventArgs se = new ServiceEventArgs(); se.Name = Name; NameChangeEvent(this, se); } public void PublishNameChangeHandler(object sender,ServiceEventArgs se) { ServiceCallback.NameChange(se.Name); } }

We have implemented our already defined three OperationContracts, and also we have defined some delegates and events. What are those? The logic is simple. Whenever a Client subscribes, we create an event handler and add to our event which is

NameChangeEvent. So, what happens here, if n number of Clients join, we have n number of event handlers
referring to those Clients.

How is this accomplished? Simple. Create a Delegate, associate an event to it, and in the DelegateHandler, we call the ServiceCallbacks NameChange contract when we want to Publish, and since it is a CallbackContract and implemented in the Client, this function would be invoked in the Client, and thus we have published our message to the Client. So, if you look in the PublishNameChangeHandler, you could see that we invoke the ServiceCallback.NameChange, which makes it clear. I have hosted the PubSubService in IIS to make things simpler. Now, let's move on to our PubSubClient.
PubSubClient

Here, we are going to add our WCF Service, implement the IPubSubContract interface to get the Callback from the Service, subscribe to the Service, and be ready to receive messages when our Publisher publishes them. Add your PubSubService through the Add Service Reference. If you are not familiar, have a look at my post regarding adding a WCF Service to your Application. Our PubSubClient is a normal Windows Forms Application, having just a Label in the Form, and this Label will be updated when a message is Published by the Publisher. I have used the PubSubService as the reference for my Service. Once you add the PubSubService, we get our PubSubService.map and PubSubService.cs through which now you can implement the IPubSubContract.
[CallbackBehaviorAttribute(UseSynchronizationContext = false)] public class ServiceCallback : IPubSubServiceCallback { public void NameChange(string Name) { Client.MyEventCallbackEvent(Name); } }

Our implementation is straightforward. We implement the NameChange contract here at our Client, and now you should be able to bring out what I meant earlier. This way, when you call from the Service using the Callback, the function in the Client would be called. What have I done in my NameChange function above? I have done Marshaling. Marshaling is used when you want to access variables in another environment or thread. And since our Windows Forms is running as a separate thread, to use safe threading, I have used Marshaling here. Implementing Marshaling is simple. We create a Delegate and associate an Event to it and make the event

static. We raise the event from the Service Callback, and update the Label control in our Form.
Below is our client class, and you can see all the Delegates, Events, and also our ServiceCallback implementation done here.
public partial class Client : Form { public delegate void MyEventCallbackHandler(string Name); public static event MyEventCallbackHandler MyEventCallbackEvent; delegate void SafeThreadCheck(string Name); [CallbackBehaviorAttribute(UseSynchronizationContext = false)] public class ServiceCallback : IPubSubServiceCallback { public void NameChange(string Name) { Client.MyEventCallbackEvent(Name); }

} public Client() { InitializeComponent(); InstanceContext context = new InstanceContext(new ServiceCallback()); PubSubServiceClient client = new PubSubServiceClient(context); MyEventCallbackHandler callbackHandler = new MyEventCallbackHandler(UpdateForm); MyEventCallbackEvent += callbackHandler; client.Subscribe(); } public void UpdateForm(string Name) { if (lblDisplay.InvokeRequired) { SafeThreadCheck sc = new SafeThreadCheck(UpdateForm); this.BeginInvoke(sc, new object[] { Name }); } else { lblDisplay.Text += Name; } } }

The only thing to keep in mind is the Marshaling. Here, I use the BeginInvoke method so that it doesn't wait for that delegate handler to complete, and the UI thread continues to do its work. If you use the Invoke method, the UI thread waits till its operation is completed. It actually depends on whether to use BeginInvoke or Invoke. You can also use Invoke here in the place of BeginInvoke.
Publisher

Publisher is the most simplest of all. We add our PubSubService, create the Service object, and just invoke the PublishNameChange contract, and thus that would invoke the ServiceCallbacks NameChange contract to the subscribed Clients, and thus exchanging the data with the Clients. Below is the Publisher code:
public partial class Publisher : Form { InstanceContext context = null; PubSubServiceClient client = null; public class ServiceCallback : IPubSubServiceCallback { public void NameChange(string Name) { MessageBox.Show(Name); } } public Publisher() { InitializeComponent(); } private void btnPublish_Click(object sender, EventArgs e) { context = new InstanceContext(new ServiceCallback()); client = new PubSubServiceClient(context); client.PublishNameChange(txtMessage.Text); client.Close(); } }

Now, we are ready to subscribe and publish ;)

Hope you had a good time reading my article on how to implement Publisher/Subscriber using WCF. If you have any queries, please feel free to drop me an email or start a discussion below.

History
Jan 10,2008 - Added the article.

License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author


chakkaradeepcc Chakkaradeep, known as Chaks to his friends, hails from the Indian subcontinent.Having done his Masters in Software Engineering, he knows his way around a computer and has sound knowledge of Microsoft technologies. Chaks is currently working as a Microsoft Developer @ New Zealand.
Software Developer New Zealand Member

You can reach him via his blog - http://chakkaradeep.wordpress.com

Comments and Discussions


15 messages have been posted for this article Visit http://www.codeproject.com/Articles/22796 /WCF-Implementation-of-the-Publisher-Subscriber-Mod to post and view comments on this article, or click here to get a print view with messages.
Permalink | Advertise | Privacy | Mobile Web04 | 2.5.120410.3 | Last Updated 9 Jan 2008 Article Copyright 2008 by chakkaradeepcc Everything else Copyright CodeProject, 1999-2012 Terms of Use

Das könnte Ihnen auch gefallen