了解Autofac中的生命周期范围的概念

时间:2016-12-14 05:14:26

标签: autofac

原谅我,我刚刚学会了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也是如此? ?

我如何通过一些实验证明它?

感谢。

1 个答案:

答案 0 :(得分:16)

我认为您首先必须了解Autofac允许注册具有不同生命周期的组件:

  • 瞬态生命周期,通过InstancePerDependency,这意味着每次要求解析组件时,容器都会创建一个新实例
  • 每个生命周期范围,通过InstancePerLifetimeScope,这意味着容器将解析为特定生命周期范围内的组件的同一实例
  • Singleton,来自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个生命周期范围已解析为服务的同一实例,并在处理根范围时处理。

编辑:缩进输出以使其更具可读性并使层次结构更清晰