原谅我,我刚刚学会了Autofac
。我有一些问题要理解Lifetime scope
中的Autofac
。请帮助查看以下内容。
假设我们有以下代码。
using(var scope = container.BeginLifetimeScope())
{
// Resolve services from a scope that is a child
// of the root container.
var service = scope.Resolve<IService>();
// You can also create nested scopes...
using(var unitOfWorkScope = scope.BeginLifetimeScope())
{
var anotherService = unitOfWorkScope.Resolve<IOther>();
}
}
正如Document所说的那样。 Lifetime scopes are disposable and they track component disposal
。
这是否意味着service
是一次性的,并且可以在声明using(var scope = container.BeginLifetimeScope())
完成后由GC回收?
嵌套范围中的anotherService
也是如此? ?
我如何通过一些实验证明它?
感谢。
答案 0 :(得分:16)
InstancePerDependency
,这意味着每次要求解析组件时,容器都会创建一个新实例InstancePerLifetimeScope
,这意味着容器将解析为特定生命周期范围内的组件的同一实例SingleInstance
。在这种情况下,组件最多只有一个实例由容器这意味着每个生命周期范围都会跟踪它拥有的组件。在处理寿命范围时,每个自有的一次性组件 - 即实施IDisposable
- 将被处置。
回到第一点,这取决于他们注册的生命周期。
如果组件已注册瞬态生命周期,则所有实例将在处置拥有生命周期范围时处理
如果它已被注册为终生使用范围,那么一个实例将在拥有生命周期范围时处理
如果组件已注册为单例,则该实例由根生命周期范围拥有,并且仅在处置该根生命周期范围时处置
public class TransientService : IDisposable
{
private static int _instanceCount = 0;
private readonly int _instanceNumber;
public TransientService()
{
_instanceCount++;
_instanceNumber = _instanceCount;
Console.WriteLine($"Just created TransientService #{_instanceNumber}");
}
public void Dispose()
{
Console.WriteLine($"Disposing TransientService #{_instanceNumber}");
}
}
public class LifetimeScopeService : IDisposable
{
private static int _instanceCount = 0;
private readonly int _instanceNumber;
public LifetimeScopeService()
{
_instanceCount++;
_instanceNumber = _instanceCount;
Console.WriteLine($"Just created LifetimeScopeService #{_instanceNumber}");
}
public void Dispose()
{
Console.WriteLine($"Disposing LifetimeScopeService #{_instanceNumber}");
}
}
public class SingletonService : IDisposable
{
private static int _instanceCount = 0;
private readonly int _instanceNumber;
public SingletonService()
{
_instanceCount++;
_instanceNumber = _instanceCount;
Console.WriteLine($"Just created SingletonService #{_instanceNumber}");
}
public void Dispose()
{
Console.WriteLine($"Disposing SingletonService #{_instanceNumber}");
}
}
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder
.RegisterType<TransientService>()
.AsSelf()
.InstancePerDependency();
builder
.RegisterType<LifetimeScopeService>()
.AsSelf()
.InstancePerLifetimeScope();
builder
.RegisterType<SingletonService>()
.AsSelf()
.SingleInstance();
using (var container = builder.Build())
{
Console.WriteLine("Created the root scope");
var rootTransientService = container.Resolve<TransientService>();
var rootLifetimeScopeService = container.Resolve<LifetimeScopeService>();
var rootSingletonService = container.Resolve<SingletonService>();
var rootTransientServiceTwo = container.Resolve<TransientService>();
var rootLifetimeScopeServiceTwo = container.Resolve<LifetimeScopeService>();
var rootSingletonServiceTwo = container.Resolve<SingletonService>();
using (var outerLifetimeScope = container.BeginLifetimeScope())
{
Console.WriteLine("Created the outer lifetime scope");
var outerTransientService = outerLifetimeScope.Resolve<TransientService>();
var outerLifetimeScopeService = outerLifetimeScope.Resolve<LifetimeScopeService>();
var outerSingletonService = outerLifetimeScope.Resolve<SingletonService>();
var outerTransientServiceTwo = outerLifetimeScope.Resolve<TransientService>();
var outerLifetimeScopeServiceTwo = outerLifetimeScope.Resolve<LifetimeScopeService>();
var outerSingletonServiceTwo = outerLifetimeScope.Resolve<SingletonService>();
using (var innerLifetimeScope = container.BeginLifetimeScope())
{
Console.WriteLine("Created the inner lifetime scope");
var innerTransientService = innerLifetimeScope.Resolve<TransientService>();
var innerLifetimeScopeService = innerLifetimeScope.Resolve<LifetimeScopeService>();
var innerSingletonService = innerLifetimeScope.Resolve<SingletonService>();
var innerTransientServiceTwo = innerLifetimeScope.Resolve<TransientService>();
var innerLifetimeScopeServiceTwo = innerLifetimeScope.Resolve<LifetimeScopeService>();
var innerSingletonServiceTwo = innerLifetimeScope.Resolve<SingletonService>();
}
Console.WriteLine("Disposed the inner lifetime scope");
}
Console.WriteLine("Disposed the outer lifetime scope");
}
Console.WriteLine("Disposed the root scope");
Console.ReadLine();
}
}
3个服务,每个生命周期一个Autofac支持。该程序非常简单,我们有根生命周期范围,外部生命周期范围和内部生命周期范围。
这些生命周期范围中的每一个都解析了每个服务的2个实例,因此每个服务都会被解析6次。 这是输出:
Created the root scope
Just created TransientService #1
Just created LifetimeScopeService #1
Just created SingletonService #1
Just created TransientService #2
Created the outer lifetime scope
Just created TransientService #3
Just created LifetimeScopeService #2
Just created TransientService #4
Created the inner lifetime scope
Just created TransientService #5
Just created LifetimeScopeService #3
Just created TransientService #6
Disposing TransientService #6
Disposing LifetimeScopeService #3
Disposing TransientService #5
Disposed the inner lifetime scope
Disposing TransientService #4
Disposing LifetimeScopeService #2
Disposing TransientService #3
Disposed the outer lifetime scope
Disposing TransientService #2
Disposing SingletonService #1
Disposing LifetimeScopeService #1
Disposing TransientService #1
Disposed the root scope
一些观察结果,始终牢记所有服务已通过 3 不同的生命周期范围 6 次解决
我们最终得到了TransientService
的6个实例,它与我们对容器的注册相匹配。处置方面,每个生命范围在处理时都处理了它们的2个实例。
仅创建了3个LifetimeScopeService
个实例。虽然每个生命周期范围都解析了此服务两次,但Autofac始终在相同的生命周期范围内返回第二次解析时的相同实例。每个实例都按照拥有的生命周期范围进行处理。
整个应用程序中只有SingletonService
个实例。此处没有生命周期范围边界,因为3个生命周期范围已解析为服务的同一实例,并在处理根范围时处理。
编辑:缩进输出以使其更具可读性并使层次结构更清晰