autofac - 理解 Autofac 中 Lifetime 范围的概念

标签 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 也是如此在嵌套范围内? ?

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

谢谢。

最佳答案

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

  • transient 生命周期,通过 InstancePerDependency ,这意味着容器每次被要求解析组件时都会创建一个新实例
  • 每个生命周期范围,通过 InstancePerLifetimeScope ,这意味着容器将解析为特定生命周期范围内的相同组件实例
  • 单例,通过 SingleInstance .在这种情况下,容器
  • 最多创建一个组件实例。

    那么组件处理跟踪是什么意思呢?

    这意味着每个生命周期范围都会跟踪它拥有的组件。在处理生命周期范围时,每个拥有的组件都是一次性的 - 即实现 IDisposable - 将被处理。

    那么我的组件什么时候会被处理掉呢?

    回到第一点,这取决于他们注册的生命周期。
  • 如果组件注册了 transient 生命周期,所有实例 将在处理拥有的生命周期范围时处理
  • 如果它已注册为 per-lifetime 范围,则 一个实例将在处理拥有的生命周期范围时处理
  • 如果组件已注册为单例,则该实例归根生命周期范围所有,并且仅在释放该根生命周期范围时才会被释放

  • 一些支持代码

    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
    

    一些观察,始终牢记所有服务都已解决 6 次由 3 不同的生命周期范围
  • 我们最终得到了 TransientService 的 6 个实例。 ,这与我们对容器进行的注册相匹配。在处置方面,每个生命周期范围在自己被处置时处置了它们的 2 个实例。
  • 只有 3 个 LifetimeScopeService 的实例被创建。虽然每个生命周期范围两次解析此服务,但 Autofac 始终在同一生命周期范围内第二次解析相同的实例时返回相同的实例。每个实例都由拥有的生命周期范围处理。
  • 只有 1 个 SingletonService 的实例在整个应用程序中。这里没有生命周期范围边界,因为 3 个生命周期范围解析为服务的同一个实例,在根范围被释放时被释放。

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

    关于autofac - 理解 Autofac 中 Lifetime 范围的概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41135292/

    相关文章:

    c# - 当构造函数注入(inject)的参数在配置和运行时已知时,从 AutoFac 获取类实例的最佳方法是什么

    c# - 手动注册所有类(class)还是有自动方式?

    c# - 如何使用 Autofac 注册开放通用接口(interface)的所有实现

    asp.net-mvc-3 - ASP.NET MVC 3 应用程序的扩展?

    c# - autofac 是否支持新的 Web Api 2

    ioc-container - Autofac:使用参数解决依赖关系

    dependency-injection - 使用 Autofac 的 OWIN 服务解析

    windows - Autofac 与 MEF 集成

    c# - 如何将 Autofac 与 Serilog 包装类一起使用

    asp.net-core - 无法在 IIS 上托管 .Net Core 3.1 Web API