Autofac:即时为每个实例创建嵌套范围

Autofac: creating nested scopes per instance on-the-fly

我想为用户创建的每个项目实现一个应用程序范围的容器和一个(嵌套的)容器。我查看了 Owned<T>,但后来——据我所知——我的内部项目集合必须是 <Owned<Project>>,这是我不想要的,而且我也未能将项目依赖项注入到项目范围内使用的对象 ("circular component dependency")。我考虑过在项目工厂中使用新的 ContainerBuilder,但是缺少 "nested" 方面。

我想要 类 的一些示例(带有依赖项):

因此,对于项目的范围,我会注册 IDocumentFactoryIProjectSettings(以及项目本身?)。

当一个项目 closed/disposed 时,所有创建的依赖项当然也应该被释放。

如果可能,具体 类(ProjectFactory 除外)应该是 Autofac 不可知的。

仅供参考:该应用程序是使用 C# 和 Autofac 4.8 的桌面应用程序。

谢谢!

更新:感谢您的评论,讨论帮助我找到了自己的观点。目前我在我的 ProjectFactory:

中设置了这样的东西
    public Project Create()
    {
        var scope = _globalScope.BeginLifetimeScope(MyIocHelper.RegisterProjectDependencies);

        var p = scope.Resolve<Project>();

        _projectScopes.Add(p, scope);
        p.Disposing += project_Disposing;

        return p;
    }

注意事项:

您可以通过命名生命周期范围和每个生命周期实例范围注册的组合来完成您正在寻找的东西。

此处的文档:http://autofac.readthedocs.io/en/latest/lifetime/working-with-scopes.html#tagging-a-lifetime-scope

您需要:

  1. 将您的 ProjectManager 注册为 SingleInstance
  2. 将项目注册为:

         builder.Register<Project>()
            .As<IProject>()
            .InstancePerMatchingLifetimeScope("project");
    

    这将保证每个标记为 "project".

  3. 的范围可以解决一次项目(例如通过文档)
  4. 在 ProjectManager 中实现一个 OpenProject(或其他)方法。此方法应实例化标记为 "project" 的 LifetimeScope,在其中注册 IDocumentFactoryIProjectSettings,以便每个项目范围仅解析一次,并将范围本身附加到 Project 实例. 这个很关键: 销毁项目的时候需要销毁作用域

    public class ProjectManager : IProjectFactory
    {
        private readonly ILifetimeScope _scope;
    
        public ProjectManager(ILifetimeScope scope)
        {
            // this is going to be the global scope.
            _scope = scope;
        }
    
    
        public Project OpenProject(IDocumentFactory docFactory, IProjectSettings settings)
        {
            var projectScope = _scope.BeginLifetimeScope("project");
            projectScope.RegisterInstance(docFactory).AsImplementedInterfaces();
            projectScope.RegisterInstance(settings).AsImplementedInterfaces();
    
            return projectScope.Resolve<Project>();
        }
    }
    
    public class ProjectScope : IDisposable
    {
        private readonly ILifetimeScope _scope;
    
        public ProjectManager(ILifetimeScope scope)
        {
            // this is going to be the project scope.
            _scope = scope;
        }
    
        public void Dispose() {
            if (_scope != null) {
                _scope.Dispose();
                _scope = null;
            }
        }
    }
    
    public class Project : IDisposable
    {
        private readonly ProjectScope _scope; 
    
        public Project(ProjectScope scope /*, ...*/)
        {
            _scope = scope;
        }
    
        public void Dispose() {
            // pay attention that this method will be called 2 times, once by you
            // and another time by the underlying LifetimeScope. So this code should
            // handle that gracefully (so the _scope == null).
            if (_scope != null) {
                _scope.Dispose();
                _scope = null;
            }
        }
    }
    

考虑到所有这些,您将每个 using Autofac 保留在每个 class 之外,除了全局管理器和 ProjectScope 的 2 个例外。如果您在 Project class 本身中接受单个 using Autofac ,则可以更改有关范围处理方式的一些位:您可以直接获取 ILifetimeScope 并处理它直接。

希望对您有所帮助!