Introduction to WebSockets with SignalR in .NET Part 5: dependency injection in Hub

Introduction

We’ve now gone through the basics of SignalR. We’ve looked at a messaging project and a primitive, but working stock ticker. Actually most of the work is put on the client in form of JavaScript code. The WebSockets specific server side code is not too complex and follows standard C# coding syntax.

However, the relative server side simplicity doesn’t mean that our code shouldn’t follow good software engineering principles. I mean principles such as SOLID, with special subjective weight given to my favourite, the letter ‘D‘.

You’ll recall from the previous post that the stock prices were retrieved from a concrete StockService class, an instance of which was created within the body of StartStockMonitoring(). The goal now is to clean up that code so that the stock prices are retrieved from an interface instead of a concrete class. The interface should then be a parameter of the ResultsHub constructor.

We’ll use StructureMap to inject the dependency into ResultsHub.cs.

Demo

I’ll use two sources from StackOverflow to solve the problem:

Let’s start by creating the abstraction. Add the following interface to the Stocks folder:

public interface IStockService
{
	dynamic GetStockPrices();
}

Then modify the StockService declaration so that it implements the abstraction:

public class StockService : IStockService

Change the ResultsHub constructor to accept the interface dependency:

private readonly IStockService _stockService;

public ResultsHub(IStockService stockService)
{
	if (stockService == null) throw new ArgumentNullException("StockService");
	_stockService = stockService;
	StartStockMonitoring();
}

Make sure you refer to the private field in the Task body of StartStockMonitoring:

Task stockMonitoringTask = Task.Factory.StartNew(async () =>
				{					
					while(true)
					{
						dynamic stockPriceCollection = _stockService.GetStockPrices();
						Clients.All.newStockPrices(stockPriceCollection);
						await Task.Delay(5000);
					}
				}, TaskCreationOptions.LongRunning);

Next, create an interface for ResultsHub in the Stocks folder:

public interface IResultsHub
{
	void Hello();
	void SendMessage(String message);
}

…and have ResultsHub implement it:

public class ResultsHub : Hub, IResultsHub

Next import the StructureMap NuGet package:

StructureMap NuGet package

We’ll need a custom HubActivator to find the implementation of IResultsHub through StructureMap. Add the following class to the solution:

public class HubActivator : IHubActivator
{
	private readonly IContainer container;

	public HubActivator(IContainer container)
	{
		this.container = container;
	}

	public IHub Create(HubDescriptor descriptor)
	{
		return (IHub)container.GetInstance(descriptor.HubType);
	}
}

IContainer is located in the StructureMap namespace.

Next insert the following class that will initialise the StructureMap container:

public static class IoC
{
	public static IContainer Initialise()
	{
		ObjectFactory.Initialize(x =>
			{
				x.Scan(scan =>
					{
						scan.AssemblyContainingType<IResultsHub>();
						scan.WithDefaultConventions();
					});
			});
		return ObjectFactory.Container;
	}
}

The last step is to register our hub activator when the application starts. Add the following code to Application_Start() in Global.asax.cs:

IContainer container = IoC.Initialise();
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new HubActivator(container));

That’s it actually. Set a breakpoint within the ResultsHub constructor and start the application. If all goes well then code execution should stop at the breakpoint. Inspect the incoming stockService parameter. If it’s null then something’s gone wrong but it shouldn’t be. Let the code execution continue and you’ll see that it works as before except that we’ve come a good step closer to loosely coupled code.

Read the finishing post in this series here.

View the list of posts on Messaging here.

Advertisements

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

7 Responses to Introduction to WebSockets with SignalR in .NET Part 5: dependency injection in Hub

  1. Kim says:

    Been reading a couple of your posts and I like them. Good explanations and very detailed. This post is also good, but I must say that I think SignalR has done a crappy job on how they do DI/IoC.

    Your work however writing about it was excellent. Keep it up!

    If I may have a request for future posts I would like to ask for this:
    You showed how SignalR can be used for sending messages to all, to others and to a specific client. But how do I send to clients based on age for example? If I want to target people between 20 – 30 years old how can I do that? Groups will not do it since they are not dynamic in that way.

    Would love a post about that topic!

    /Kim

    • Andras Nemes says:

      Hi Kim, thanks for your feedback. Your request sounds very interesting, I’ll think about it.
      //Andras

    • Andras Nemes says:

      …I’m aiming to have a solution next Monday when the next “long” is due.
      //Andras

      • Kim says:

        Sounds great! Thank you!

        What I would really like is a SignalR way of doing it like they do it in xsockets.net.
        If using the age example in xsockets I would do…

        this.SendTo(p => p.Age >= 20 && p.Age <= 30, objectToSend, "topic");

        If you can show me that I will be very happy!

      • Andras Nemes says:

        …there it is, check out today’s post. It’s not exactly the way you’ve specified but it’s the closest I could get.
        //Andras

      • Kim says:

        Thank you very much for your efforts! I think you example (post nr 6) is a nice way of showing how to achieve some of functionality I need.

        Unfortunatelly the way SIgnalR works does not cover my needs in this case. I have to combine Age, Gender and Interest. So I have 3 dynamic criterias… I am sure you can see my concern. I have solved it with one line in xsockets since I can use

        this.SendTo(Func condition, object o, string topic);

        I have been using SignalR for a long time but I just dont know how to get past this right now.

        Thanks again for your extra post, I really enjoy reading your blog.

        Thank you
        Kim

  2. سعيد says:

    Hello,
    Thanks for this introduction.
    There are few notes about ‘Task.Factory.StartNew’ and also creating a new unnecessary thread in web applications. more info:
    http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html

Leave a Reply to سعيد Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: