Skip to content

Instantly share code, notes, and snippets.

@pmbanugo
Created August 11, 2016 10:41
Show Gist options
  • Save pmbanugo/99933fc8ec58e96e8e6a7f972ed9e5be to your computer and use it in GitHub Desktop.
Save pmbanugo/99933fc8ec58e96e8e6a7f972ed9e5be to your computer and use it in GitHub Desktop.
Using SimpleInjector with SignalR: Injecting Services into SignalR Hubs.
public class ChatHub : Hub
{
private readonly Container _container;
public ChatHub(Container container)
{
_container = container;
}
public override Task OnConnected()
{
var userId = Context.User.GetUserID();
_container.GetInstance<IChatService>().OnConnected(userId, Context.ConnectionId, Clients);
return base.OnConnected();
}
public override Task OnDisconnected()
{
using (_container.BeginExecutionContextScope())
{
var userId = Context.User.GetUserID();
_container.GetInstance<IChatService>().OnDisconnected(userId, Context.ConnectionId, Clients);
return base.OnDisconnected();
}
}
public void Broadcast(string message)
{
_container.GetInstance<IChatService>().Broadcast(message, Context.User.Identity.Name, Clients);
}
}
public class ChatService : IChatService
{
private readonly IUnitOfWork _unitOfWork;
public ChatService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void OnConnected(Guid userId, string connectionId, HubConnectionContext clients)
{
var existingConnection = _unitOfWork.UserConnectionRepository.Get(x => x.UserId == userId);
if (!existingConnection.Any())
{
//TODO: get username from db
clients.Others.userOnline(userId, DateTime.UtcNow.TimeOfDay);//notify other connected users
}
SaveUserConnection(userId, connectionId);
var onlineUsers = _unitOfWork.UserConnectionRepository.GetOnlineUsers().Select(userConnection => new
{
name = userConnection.Name,
id = userConnection.UserId
});
clients.Caller.setOnlineUsers(onlineUsers);
}
private void SaveUserConnection(Guid userId, string userConnectionId)
{
try
{
var userConnection = new UserConnection() { ConnectionId = userConnectionId, UserId = userId };
_unitOfWork.UserConnectionRepository.Insert(userConnection);
_unitOfWork.SaveChanges();
}
catch (Exception)
{
//TODO: Log exception
}
}
public void OnDisconnected(Guid userId, string connectionId, HubConnectionContext clients)
{
try
{
_unitOfWork.UserConnectionRepository.Delete(userId, connectionId);
_unitOfWork.SaveChanges();
}
catch (Exception)
{
//TODO: log exception
}
var existingConnection = _unitOfWork.UserConnectionRepository.Get(x => x.UserId == userId);
if (!existingConnection.Any())
{
//TODO: get username from db
clients.All.userOffline(userId); //notify other connected users
}
}
public void Broadcast(string message, string username, HubConnectionContext clients)
{
var time = DateTime.Now.ToString("D") + " at " + DateTime.Now.ToString("h:mm:ss tt");
string picture;
clients.All.newMessage(message, username, time);
}
}
public interface IChatService
{
void OnConnected(Guid userId, string connectionId, HubConnectionContext clients);
void OnDisconnected(Guid userId, string connectionId, HubConnectionContext clients);
void Broadcast(string message, string username, HubConnectionContext clients);
}
.....
// Create the container as usual.
var container = new Container();
//hybrid lifestyle
var hybrid = Lifestyle.CreateHybrid(
() => container.GetCurrentExecutionContextScope() != null,
new ExecutionContextScopeLifestyle(),
new SimpleInjector.Integration.Web.WebRequestLifestyle());
.........
container.Register(() => new DataAccess.EF.DataContext(), hybrid);
container.Register<IUnitOfWork, UnitOfWork>(hybrid);
container.Register<IChatService, ChatService>(hybrid);
.......
var activator = new SimpleInjectorHubActivator(container);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => activator);
...........
Tip: instead of reusing hybrid variable throught the composition root, you can also set it as the default scoped lifestyle
like this (it all depends on what you want):
container.Options.DefaultScopedLifestyle = hybrid;
container.Register<IChatService, ChatService>(Lifestyle.Scoped);
.....
public class SimpleInjectorHubActivator : IHubActivator
{
private readonly Container _container;
public SimpleInjectorHubActivator(Container container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
return (IHub)_container.GetInstance(descriptor.HubType);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment