1

I am trying to set up my AutoFac registration in such a way that this test passes:

[Test]
public void Autofac_registration_test()
{
    // Given
    var builder = new ContainerBuilder();
    RegisterServices(builder);
    var container = builder.Build();

    // When
    var firstHub = container.Resolve<Hub>();
    var secondHub = container.Resolve<Hub>();

    // Then
    firstHub.Should().NotBe(secondHub);
    firstHub.FooRepo.Context.Should().Be(firstHub.BarRepo.Context);
    firstHub.FooRepo.Context.Should().NotBe(secondHub.FooRepo.Context);
}

i.e. I want to use the same Context object all the way down within a single Hub, but use a different one when a new Hub is created.

RegisterServices is currently just:

private void RegisterServices(ContainerBuilder builder)
{
    builder.RegisterType<MyHub>();
    builder.RegisterType<FooRepo>();
    builder.RegisterType<BarRepo>();
    builder.RegisterType<Context>(); // How should I scope this?
}

Which fails at firstHub.FooRepo.Context.Should().Be(firstHub.BarRepo.Context); because Context is transiently scoped.

But scoping context per lifetime also fails, this time at firstHub.FooRepo.Context.Should().NotBe(secondHub.FooRepo.Context);.

It feels like this is a reasonable thing to want to do, so am I missing anything obvious out-of-the-box here? Or will I have to do something manual to track Hub creation?

(For context, this is for a SignalR app. Hubs are created per SignalR request, so this was an attempt to match the unit-of-work lifetime of an HTTP request in normal webby situations).

Jamie Humphries
  • 3,368
  • 2
  • 18
  • 21
  • Also, I am not totally married to AutoFac. If there is another dependency injection framework that handles this gracefully that would be fine too! – Jamie Humphries Sep 04 '14 at 16:38
  • 2
    Partial answer: It's probably going to involve named lifetime scopes. This answer may have enough info to get you going: http://stackoverflow.com/a/16820778/540663 – Jim Bolla Sep 04 '14 at 16:48
  • 3
    What you are looking for is the per-object-graph lifestyle, which is something not many containers support. AFAIK Autofac doesn't either. The usual way to handle this is by starting a new lifetime scope A @JimBolla said. – Steven Sep 04 '14 at 17:04

1 Answers1

2

What @Steven said in his comment was correct, I needed a per-object-graph lifestyle.

Castle.Windsor supports this, so I swicthed to using that for my dependency injection instead of AutoFac. The registration now looks like:

container.Register(Component.For<Hub>().LifestyleTransient());
container.Register(Component.For<FooRepo>().LifestyleTransient());
container.Register(Component.For<BarRepo>().LifestyleTransient());
container.Register(Component.For<Context>().LifestyleBoundTo<Hub>()); // Important bit

For more information, see: http://docs.castleproject.org/Windsor.LifeStyles.ashx?HL=scope#Bound_8

Jamie Humphries
  • 3,368
  • 2
  • 18
  • 21