根容器范围可以访问子范围的注册吗?

Can root container scope access child scopes' registrations?

我们知道 Autofac 有嵌套作用域的概念,子作用域从父作用域继承注册。假设我们有以下代码:

class Program
{
   static void Main(string[] args) {
      var builder = new ContainerBuilder();
      builder.RegisterType<Owner>().As<IOwner>().SingleInstance();
      IContainer container = builder.Build();

      using (var childScope1 = container.BeginLifetimeScope(b => { b.RegisterType<Dog>().As<IDog>().InstancePerDependency(); })) {
         IOwner owner= childScope1.Resolve<IOwner>();
      }
      // the injected Dog instance will be disposed when childScope1 is disposed


      using (var childScope2 = container.BeginLifetimeScope()) {
         IOwner owner = childScope2.Resolve<IOwner>();
      }
   }
}

// those interfaces, classes , inheritances are non meaningful, just for demo purpose
public interface IOwner: IDisposable { }

public interface IDog : IDisposable { }

public class Owner: IOwner{
   IDog dog;
   public Owner(IDog dog) {
      this.dog = dog;
   }
   public void Dispose() { ...}
}

public class Dog: IDog {
   public void Dispose() { ...}
}

可以看到我在childScope1中注册Dog IDog为transient,Owner依赖IDog。因此,当我在 childScope1 中解析 IOwner 时,单例 Owner 实例将从根容器生命范围中解析,但它的依赖项 Dog 在 childScope1 中解析,因为我在中注册了 Dog子范围不在根范围内。所以在第一个 using 语句之后,瞬态 Dog 实例被释放(因为 childScope1 被释放)。

所以我的问题是,当它的依赖项 Dog 已经被释放时,单例共享实例 owner 如何在 childScope2 中正常工作?如果可以正常工作,是否意味着根容器作用域可以访问子作用域的注册?

我实际上不确定您提供的代码是否有效。你试过了吗,还是假设的?解析单例将尝试解析根生命周期范围(容器)中的所有依赖项,并且由于根中不存在依赖项注册,解析将失败。

关于其工作原理的更大问题的答案是 covered pretty well in the documentation,其中包括有用的图表。这是一个相关的片段:

What affects this mechanism is the “lifetime” aspect of “lifetime scope.” Some components, like singletons need to be shared across multiple scopes. This affects how dependencies get located. The “basic rules” are:

  • A child lifetime scope can get dependencies from parent scopes, but a parent scope may not reach down into a child scope. (You can locate things by moving “up the tree” but you can’t move “down the tree.”)
  • A component will get its dependencies from the scope that owns the component even if the component is resolved by a scope further down the tree.

通过编写一些小的单元测试并获得实践经验,可以以更实用的方式回答很多问题。您还可以浏览现有的 Autofac 单元测试和示例以查看实际代码。