AutoFac
Scopes & Lifetimes

Scopes
- There is no global 'scope' context
- Registrations will only be resolved from the ILifetimeScope returned by BeginLifetimeScope.
using (ILifetimeScope parentScope = CreateContainer()) { using (ILifetimeScope childScope1 = parentScope.BeginLifetimeScope(b => b.RegisterType<MyType>().SingleInstance())) using (ILifetimeScope childScope2 = parentScope.BeginLifetimeScope(b => b.RegisterType<MyType>().SingleInstance())) { MyType result1 = childScope1.Resolve<MyType>(); MyType result2 = childScope2.Resolve<MyType>(); result1.ShouldNotReferTo(result2); } }
Scopes
- Child scopes do not affect parent scopes.
- Child scopes inherit registrations from parent scopes.
- Similar as class inheritance, don't create a child scope unless you need what's in the parent scope
Scopes
- Must be disposed!
- Scopes have DisposalManagers - you can register a scope to be disposed when another scope is disposed.
- Watch out for scopes shared between threads.
When to create scopes
- Almost never. Ideally there should be only one resolve, which means only one scope.
- In reality, we need to create a scope per resource view.
- We also have scopes for printing.
Lifetimes
Default is InstancePerDependency.
[Test] public void InstancePerDependency_NewInstanceCreatedEveryTime() { using (ILifetimeScope scope = CreateContainer(builder => builder.RegisterType<MyType>())) { MyType instance1 = scope.Resolve<MyType>(); MyType instance2 = scope.Resolve<MyType>(); instance1.ShouldNotReferTo(instance2); } }
Lifetimes
SingleInstance is scoped to where it's registered.
[Test] public void SingleInstance_IsScopedToWhereRegistrationOccurs() { using (ILifetimeScope outerScope = CreateContainer(b => b.RegisterType<MyType>())) { using (ILifetimeScope middleScope = outerScope.BeginLifetimeScope(b => b.RegisterType<MyType>().SingleInstance())) { using (ILifetimeScope innerScope = middleScope.BeginLifetimeScope()) { MyType outerResult = outerScope.Resolve<MyType>(); MyType innerResult = innerScope.Resolve<MyType>(); MyType middleResult = middleScope.Resolve<MyType>(); outerResult.ShouldNotReferTo(middleResult); innerResult.ShouldReferTo(middleResult); } } } }
Lifetimes
InstancePerLifetimeScope will be one per scope.
[Test] public void InstancePerLifetimeScope_OneInstancePerScope() { using (ILifetimeScope outerScope = CreateContainer(b => b.RegisterType<MyType>().InstancePerLifetimeScope())) { using (ILifetimeScope innerScope = outerScope.BeginLifetimeScope()) { MyType outerInstance1 = outerScope.Resolve<MyType>(); MyType outerInstance2 = outerScope.Resolve<MyType>(); MyType innerInstance = innerScope.Resolve<MyType>(); outerInstance1.ShouldReferTo(outerInstance2); innerInstance.ShouldNotReferTo(outerInstance1); } } }
When to use non-default lifetimes
- Almost never - only if state needs to be shared between consumers.
- Don't worry about performance - there's no logic in your constructors, right?
RIGHT‽

Registrations
- How do you find out where something is registered?
- Press Shift-Alt-F12, then type module
- Agent Mulder plugin for R#
Registrations
What happens if there's no explicit registration?

Registrations
- Explicit registrations are best
- .As<Interface>() not .AsImplementedInterfaces()
- RegisterAssemblyTypes only for interfaces with many implementations
- ICommand
- Controller
- Last registration for an interface wins
- Great for explicit registrations
- Not so great for automatic registrations
Registrations
Avoid confusing errors & behaviour
- Don't register types in scopes that shouldn't need them
- IResourceRepository
- Separate modules by 'module' of code
- Resource modules
Don't be this dog
AutoFac
By soxtoby
AutoFac
- 28