Search code examples
c#autofaclifetime-scoping

Autofac Conundrum


I use Autofac as my IoC container of choice. The rest of this question refers to SignalR in conjunction with SignalR, but no real SignalR knowledge is needed to answer; this is a problem rooted in Autofac.

As part of using Autofac as the dependency resolver for SignalR, I want to provide my own IJsonSerializer instance configured how I like it. I don't, however, want to have that IJsonSerializer instance shared throughout the rest of the software.

To accomplish this, I created a new lifetime scope with the additional registration, and provided that scope to the dependency resolver. This is when my problems started.

What I didn't realize is by doing this, instance-per-lifetime-scope dependencies requested from SignalR which had previously been retrieved from the root container are now being requested from a lifetime scope, and thus are shared across the entirety of SignalR. This is not good. For example, short-lived database sessions are now shared for the lifetime of my application.

How can I cause my instance-per-lifetime-scope dependencies to basically pretend that the lifetime scope I pass to SignalR should not be used to cause those dependencies to be reused? Alternatively how can I avoid creating the lifetime scope altogether?


Solution

  • Question is a few months old but I thought I would share with you the method I used (perhaps someone can improve on it).

    I added an event to my hub, to fire once the hub was disposing. (Actually through a base hub as I had some common logic already in place anyway)

    public event Action OnDisposing;
    
    protected override void Dispose(bool disposing)
    {
        if (OnDisposing != null) OnDisposing.Invoke();
    }
    

    With this in place I then modified how autofac registers this hub. When resolving, a new lifetime scope is created and the scope's dispose method is set to fire when the hub is disposed.

    builder.Register(x =>
    {
        ILifetimeScope scope = x.Resolve<ILifetimeScope>().BeginLifetimeScope();
        MyHub hub = new MyHub(scope.Resolve<IMyDependency>());
        hub.OnDisposing += scope.Dispose;
        return hub;
    })
    .As<MyHub>().InstancePerDependency();