Autofac 实例的作用域与生命周期

作用域和类型:

  • 每个依赖一个实例(Instance Per Dependency)
  • 单一实例(Single Instance)
  • 每个生命周期作用域一个实例(Instance Per Lifetime Scope)
  • 每个匹配的生命周期作用域一个实例(Instance Per Matching Lifetime Scope)
  • 每个请求一个实例(Instance Per Request)
  • 每次被拥有一个实例(Instance Per Owned)
  • 线程作用域(Thread Scope)

每个依赖一个实例(Instance Per Dependency)

即瞬时,每次使用Resolve生成实例,都会new一个,对于一个服务每次请求都会返回一个唯一的实例.
如果没有指定特定的选项, 它将是默认的.

var builder = new ContainerBuilder();

// This...
builder.RegisterType<Worker>();

// ...is the same as this:
builder.RegisterType<Worker>().InstancePerDependency();


using(var scope = container.BeginLifetimeScope())
{
  for(var i = 0; i < 100; i++)
  {
    // Every one of the 100 Worker instances
    // resolved in this loop will be brand new.
    var w = scope.Resolve<Worker>();
    w.DoWork();
  }
}

单一实例(Single Instance)

无论从哪里解析,都获得相同的实例

var builder = new ContainerBuilder();
builder.RegisterType<Worker>().SingleInstance();

每个生命周期作用域一个实例(Instance Per Lifetime Scope)

作用域单例

var builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerLifetimeScope();
using(var scope1 = container.BeginLifetimeScope())
{
  for(var i = 0; i < 100; i++)
  {
    // Every time you resolve this from within this
    // scope you'll get the same instance.
    var w1 = scope1.Resolve<Worker>();
  }
}

using(var scope2 = container.BeginLifetimeScope())
{
  for(var i = 0; i < 100; i++)
  {
    // Every time you resolve this from within this
    // scope you'll get the same instance, but this
    // instance is DIFFERENT than the one that was
    // used in the above scope. New scope = new instance.
    var w2 = scope2.Resolve<Worker>();
  }
}

每个匹配的生命周期作用域一个实例(Instance Per Matching Lifetime Scope)

当你创建一个嵌套的生命周期作用域时, 你可以给作用域 “打标签” 或者 “命名” . 每个匹配生命周期作用域的组件在每个名称匹配的嵌套生命周期作用域中最多只会有一个单一实例. 这就允许了你创建一系列 “有作用域的单例” , 其他嵌套的生命周期可以在不声明一个共享实例的情况下共享这种组件的实例.

它对于单个独立工作单元特定的对象非常有用, 例如, 一个 HTTP 请求, 它作为一个嵌套的生命周期在每个工作单元内都会被创建. 如果一个嵌套的生命周期每个 HTTP 请求创建一次, 那么任何每个生命周期作用域的组件在每个 HTTP 请求内都将只有一个实例.

var builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerMatchingLifetimeScope("myrequest");
// Create the lifetime scope using the tag.
using(var scope1 = container.BeginLifetimeScope("myrequest"))
{
  for(var i = 0; i < 100; i++)
  {
    var w1 = scope1.Resolve<Worker>();
    using(var scope2 = scope1.BeginLifetimeScope())
    {
      var w2 = scope2.Resolve<Worker>();

      // w1 and w2 are always the same object
      // instance because the component is per-matching-lifetime-scope,
      // so it's effectively a singleton within the
      // named scope.
    }
  }
}

// Create another lifetime scope using the tag.
using(var scope3 = container.BeginLifetimeScope("myrequest"))
{
  for(var i = 0; i < 100; i++)
  {
    // w3 will be DIFFERENT than the worker resolved in the
    // earlier tagged lifetime scope.
    var w3 = scope3.Resolve<Worker>();
    using(var scope4 = scope3.BeginLifetimeScope())
    {
      var w4 = scope4.Resolve<Worker>();

      // w3 and w4 are always the same object because
      // they're in the same tagged scope, but they are
      // NOT the same as the earlier workers (w1, w2).
    }
  }
}

// You can't resolve a per-matching-lifetime-scope component
// if there's no matching scope.
using(var noTagScope = container.BeginLifetimeScope())
{
  // This throws an exception because this scope doesn't
  // have the expected tag and neither does any parent scope!
  var fail = noTagScope.Resolve<Worker>();
}

每个请求一个实例(Instance Per Request)

ar builder = new ContainerBuilder();
builder.RegisterType<Worker>().InstancePerRequest();

每次被拥有一个实例(Instance Per Owned)

实例的生命周期绑定到其它作用域上

var builder = new ContainerBuilder();
builder.RegisterType<MessageHandler>();
builder.RegisterType<ServiceForHandler>().InstancePerOwned<MessageHandler>();
using(var scope = container.BeginLifetimeScope())
{
  // The message handler itself as well as the
  // resolved dependent ServiceForHandler service
  // is in a tiny child lifetime scope under
  // "scope." Note that resolving an Owned
  // means YOU are responsible for disposal.
  var h1 = scope.Resolve<Owned<MessageHandler>>();
  h1.Dispose();
}

线程作用域(Thread Scope)

var builder = new ContainerBuilder();
builder.RegisterType<MyThreadScopedComponent>()
       .InstancePerLifetimeScope();
var container = builder.Build();
void ThreadStart()
{
  using (var threadLifetime = container.BeginLifetimeScope())
  {
    var thisThreadsInstance = threadLifetime.Resolve<MyThreadScopedComponent>();
  }
}

在这种多线程场景中, 你必须得注意父级作用域不能在派生出的线程下被释放了. 否则你就会碰到一个很糟糕的情况, 如果你派生了一个子线程并在其中释放了父级作用域, 组件就不能解析了.

你可能感兴趣的:(C#)