I had the opportunity to work on a project where it made sense to implement SignalR into a .NET MVC project to send live updates to our users. The existing code base uses StructureMap for dependency injection and I wanted to extend this to our SignalR implementation. I found a lot of bits and pieces on implementing StructureMap as the dependency injection container but not a complete overview. After hours of trial and error using StructureMap I finally arrived at a solution which works. Hopefully what I found will save you quite a bit a time if you're planning on using StructureMap and SignalR.

Find the source code in my Git Repository here.

If you are familiar with SignalR already you probably want to skip to here.

Getting Started

(Note - I am using Visual Studio 2013 for this walkthrough, you could also use Visual Studio 2012)

So to start off create a new Visual Studio Web Application (if you are using Visual Studio 2012 make sure you target .Net 4.5), I'm naming mine "SignalRStructureMapWalkthrough":
Create A Visual Studio Web Application

After hitting "OK", select "Empty" to create an empty web project, the OK again.
Select Empty Web App

Including SignalR

Next we're going to get SignalR up and running in our solution, first we'll start by downloading the SignalR package from NuGet. Please note that this package installs several perquisites.
Add Required New Get Packages

After we've installed the core SignalR package we'll install a sample application the SignalR team has put together. We could have just installed the sample application and gotten the core SignalR packages, however I wanted to install SignalR as you would in your applications. Back in the NuGet package manager window search for "SignalR Sample". Then install the "Microsoft.AspNet.SignalR.Sample" package.
Add SignalR Sample Package

Again, when installation is complete you'll see a readme appear. This time we're going to follow the instructions:

Step One (Create an OWIN startup class in your application if you don't already have one.):

  • Create a new folder in your project, I'm going to call mine: App_Start
  • In your new folder create a plain old C# class, I named mine: SignalRStartup.
  • In your new class add the following code from the readme.text file, you'll want to make sure to change "MyWebApplication" to the name of your project, in my case "SignalRStructureMapWalkthrough":
using Microsoft.Owin;  
using Owin;

[assembly: OwinStartup(typeof(SignalRStructureMapWalkthrough.Startup), "Configuration")]

namespace SignalRStructureMapWalkthrough  
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {                       Microsoft.AspNet.SignalR.StockTicker.Startup.ConfigureSignalR(app);
        }
    }
}

When completed your project should look like this:
After SignalR Configured

What does the class we added do? It creates an OwinStartup class which will be executed by IIS when our application is started. The "Configuration" method will configure SignalR. We'll be hooking some dependency injection code here in a bit.

Run the Project

Well, after all that work, let's see if this thing actually runs! Build the project then right click on "StockTicker.html" in the "SignalR.Sample" folder, if everything is working you should see a table with stock ticker symbols, click the "Open Market" button and the action should begin.
It worksIt works!

Implement StructureMap

Alright, now that we've gotten the setup out of the way it's time to get to business. First we are going to install the latest version of StructureMap from NuGet. Using the package manager you can search for StructureMap and install.

NuGet StructureMap

Ok, so from here on out, this guide is based on the SignalR documentation on how to implement dependency injection using Ninject adjusted for StructureMap.

Getting the existing code ready

So what we want to do is be able to be able inject any instance that implements a IStockTicker interface into our Hub. So we are going to start by:

  • Removing the Singleton instance in the StockTicker class.
  • Extracting an interface for the public methods on the StockTicker class.
  • Make existing constructor public
Removing the Singleton instance from the StockTicker class
Remove the code commented out below:
// Singleton instance - COMMENT THIS OUT (or better yet remove :))...
//private readonly static Lazy<StockTicker> _instance = new Lazy<StockTicker>(
//  () => new StockTicker(GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>().Clients));

//REMOVE
//public static StockTicker Instance
//{
//    get
//    {
//        return _instance.Value;
//    }
//}

//MAKE THIS CONSTUCTOR PUBLIC
public StockTicker(IHubConnectionContext clients)  
{
    Clients = clients;
    LoadDefaultStocks();
}

Extracting an interface for the public methods on the StockTicker class.

Ok, in order to inject an instance of the StockTicker class into the StockTickerHub we need to create a interface for the StockTicker class, that looks like this (I just created my interface in the StockTicker.cs file):
public interface IStockTicker  
{
    void CloseMarket();
    IEnumerable<Stock> GetAllStocks();
    MarketState MarketState { get; }
    void OpenMarket();
    void Reset();
}
The last step is to have the StockTicker implement the IStockTicker interface.
//StockTicker should now implement IStockTicker
public class StockTicker : IStockTicker  

Updating the Hub Class

Instead using a concrete implementation when creating the Hub we're now going to use our implementation, here is the updated code in the Hub class:
[HubName("stockTicker")]
public class StockTickerHub : Hub  
{
    //Change to use the interface
    private readonly IStockTicker _stockTicker;

    //Remove this constructor
    //public StockTickerHub() : this(StockTicker.Instance) { }

//Changing this to the interface
    public StockTickerHub(IStockTicker stockTicker)
    {
        _stockTicker = stockTicker;
    }

    //(The remainder of the class has been omitted for brevity)

Configuring StructureMap

SignalR has a built in dependency resolution container, this is the DefaultDependencyResolver, first we're going to create our own dependency resolver with the DefaultDependencyResolver as the base class. I'm including this file in my SignalRStartup.cs file for simplicity.

public class StructureMapSignalRDependencyResolver : DefaultDependencyResolver  
{
    private readonly IContainer _container;
        public StructureMapSignalRDependencyResolver(IContainer container)
        {
            _container = container;
        }

        public override object GetService(Type serviceType)
        {
            object service = null;
            //Below is a key difference between this StructureMap example, GetInstance is used for concrete classes.
            if (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
            {
                //If the type is a concrete type we get here...
                service = _container.GetInstance(serviceType);
            }
            else
            {
                // Non concrete resolution which uses the base dependency resolver if needed.
                service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);
            }
            return service;
        }

        public override IEnumerable<object> GetServices(Type serviceType)
        {
            var objects = _container.GetAllInstances(serviceType).Cast<object>();
            return objects.Concat(base.GetServices(serviceType));
        }
    }
StructureMap Container Configuration
Alright, here is where things get really interesting, in order to spin up an instance of our hub which can communicate with our clients (using the IHubConnectionContext) we need to tell StructureMap what to use when an instance of IHubConnectionContext is requested. Here is the StructureMap code to do that (in SignalRStartup.cs)
  
var container = ObjectFactory.Container;  
var resolver = new StructureMapSignalRDependencyResolver(container);  
ObjectFactory.Configure(x =>  
    x.For<Microsoft.AspNet.SignalR.StockTicker.IStockTicker>()
                    .Singleton()
                    .Use<Microsoft.AspNet.SignalR.StockTicker.StockTicker>();
    x.For<IHubConnectionContext>().ConditionallyUse(c =>
                    c.If(t => t.ParentType.GetInterface(typeof(Microsoft.AspNet.SignalR.StockTicker.IStockTicker).Name) ==
                        typeof(Microsoft.AspNet.SignalR.StockTicker.IStockTicker))
                        .ThenIt.Is.ConstructedBy(
                            () => resolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients)
                    );
            });    
    
Here is what is going on above...
    
x.For<Microsoft.AspNet.SignalR.StockTicker.IStockTicker>()
                    .Singleton()
                    .Use<Microsoft.AspNet.SignalR.StockTicker.StockTicker>();
If there is a request for an instance which implements IStockTicker, create a singleton instance of StockTicker. This statement is used when spinning up an instance of the StockTickerHub.

x.For<IHubConnectionContext>().ConditionallyUse(c =>
                    c.If(t => t.ParentType.GetInterface(typeof(Microsoft.AspNet.SignalR.StockTicker.IStockTicker).Name) ==
                        typeof(Microsoft.AspNet.SignalR.StockTicker.IStockTicker))
                        .ThenIt.Is.ConstructedBy(
                            () => resolver.Resolve<IConnectionManager>().GetHubContext<StockTickerHub>().Clients)
                    );    
What the code above is doing is since IStockTicker requires a instance of IHubConnectionContext when it is instantiated we need to use the custom dependency resolver we created earlier to resolve it. Note that the conditional logic makes sure that IHubConnectionContext is only instantiated for objects which inherit IStockTickerHub (if you create other hubs you would need to add a statement for them as well). #####Finishing Up Ok, now that we have the proper StructureMap container we just need to make sure it gets registered with SignalR. We'll start by adding the following code under the StructureMap contain we configured in the last section:

var config = new HubConfiguration()
{
    Resolver = resolver
};

//Pass config into ConfigureSignalR method. Microsoft.AspNet.SignalR.StockTicker.Startup.ConfigureSignalR(app, config);
What we're doing here is creating a new HubConfiguration with our custom dependency resolver which will we tell SignalR to use. We then pas this new config instance to our SignalR "ConfigureStartup" method. Now we need to change the "ConfigureStartup" method to take a parameter of HubConfiguration and use it in the "MapSignalR" method.

public static void ConfigureSignalR(IAppBuilder app, HubConfiguration config)
{
  //Changed this method to accept a HubConfiguration parameter
  //and pass it off to the MapSignalR method
  app.MapSignalR(config);
}

Once that is done, you should be able to build and run the project as you could prior to implementing StructureMap, now you easily inject any other dependencies into your SignalR Hubs and helper classes!

References

comments powered by Disqus

About Author

Jerod Krone

Jerod Krone