HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Local (In-Process) Publish/Subscribe

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
publishlocalsubscribeprocess

Problem

I have a handful of objects that don't have references to each-other that all need to receive an update.

From what I've read, it seems like a Publish-Subscribe Messaging Channel is an appropriate pattern. Searching for an existing solution mainly turned up messaging libraries for application integration (between processes). Those solutions were much more than what I needed, so I wrote this simple Publisher.

Questions:

  • Is there already something simple like this in the .NET framework that I overlooked? Or another light-weight library?



  • Is this an appropriate implementation and application of the Pub/Sub pattern? What might be done to improve it?



  • What gotchas are there? For example, I presume I need to Unsubscribe in the subscriber's finalizer.



```
public interface ISubscriber
{
void SubscriptionUpdate(object message);
}

public interface IPublisher
{
void Subscribe(ISubscriber subscriber, string channel);
void Unsubscribe(ISubscriber subscriber, string channel);
void Publish(string channel, object message);
}

public class Publisher : IPublisher
{
static Publisher _instance = new Publisher();
public static Publisher Instance { get { return _instance; } }
Dictionary> _subscribers = new Dictionary>();

public void Subscribe(ISubscriber subscriber, string channel)
{
if (!Exists(channel))
_subscribers[channel] = new List();
if (!_subscribers[channel].Contains(subscriber))
_subscribers[channel].Add(subscriber);
}

public void Unsubscribe(ISubscriber subscriber, string channel)
{
if (Exists(channel))
_subscribers[channel].Remove(subscriber);
}

public void Publish(string channel, object message)
{
if (!Exists(channel)) return;
foreach (var subscriber in _subscribers[channel])
subscriber.SubscriptionUpdate(message);
}

bool Exists(string channel)
{
return _subscribers.ContainsKey(channel);
}
}

Solution

Update (2022): If you do want to use an in-process publish-subscribe pattern - consider using a very popular package MediatR. Events are kind of a legacy approach now.

Original answer (2013):
Don't think it's a good approach.

  • Singletons are evil by themselves



  • Subscribers are likely to expect a specific type of message on specific channel



  • Magic strings that specify the channel name are also potential source of bugs



  • Incorrect messages or posts to wrong channels are detected at run-time only.



  • Logical dependency between objects still exist, but is hidden.



.NET already has a notion of in-process publish/subscribe, and (not that surprisingly) this functionality is covered by events... All you need to do is to wire up all your entities properly, and that's your actual challenge is.

I would recommend using any of available IoC frameworks for that (I use Autofac at the moment).

  • You will have a strictly-typed communication protocol between publisher and subscriber



  • It will allow you to explicitly declare dependency on a certain external functionality in your classes.



  • It will simplify unit-testing of your classes



Unfortunately you haven't described specific use cases for your pub/sub requirement so it's hard to show this solution on specific example

Context

StackExchange Code Review Q#26730, answer score: 2

Revisions (0)

No revisions yet.