0

我们已从 Windows Framework 4.7 应用程序迁移到 .NET 6.0。为依赖注入添加了 Lamar。我们正在尝试完成对最新“单文件”program.cs 的重构,但出现意外 System.ObjectDisposedException:“无法访问已处置的对象”。在所有情况下,错误都是针对Func<T>对象创建期间的。

我们所有的测试都使用相同的环境正确运行,除了开始测试我们(a)创建 DI 容器和(b)使用容器创建加载单例的对象(来自 MongoDB):

Container = new Container(registry);
var start = Container.GetInstance<HomeService>();

在 program.cs 中,我们配置容器,但看不到它已创建或在 program.cs 中访问它。相反,我们在第一次使用控制器期间从 IServiceProvider 创建 HomeService。在这里,我们试图在创建期间限制生命周期范围:

using (var scope = _container.CreateScope())
            {
                scope.ServiceProvider.GetService<INewHomeService>(); 
            }

对于测试,我们使用相同的加载步骤,当然,除了添加控制器/mvc(即不使用 builder.Services.AddControllers(); 和 builder.Services.AddMvc() 进行(集成)测试)。

我们尝试了很多不同的事情,比如独立于启动创建我们的对象,但这并没有对齐单例。我们可以通过使用静态来获得功能,但随后我们失去了动态更改访问权限。

一些很棒的技巧,例如在 ConfigureServiceshttps://andrewlock.net/exploring-dotnet-6-part-10-new-dependency-injection-features-in-dotnet-6/中使用 ASP.NET Core DI 解析实例,但我在初始创建后看不到获取实时容器的具体示例。

问题是否可能只是新的 .NET DI 实现的生命周期管理之间的区别?由于这是组合根的配置,如果我们可以按照我们的测试方法进行配置,它应该可以解决我们的问题。欢迎其他解决方案!

4

1 回答 1

0

“无法访问已处置的对象”问题是由保留的上下文和控制器访问之间的生命周期不匹配引起的。该代码保留了状态对象的句柄,该句柄具有使用 FUNC 的工厂句柄。由于我们没有将 Func 配置为任何东西,它在控制器图创建过程中是瞬态的,因此在控制器请求结束时被释放。

为了解决这个问题,我们尝试按照如何在内置依赖注入中使用 Func<T>注册所有 FUNC,这是一项艰巨的任务,因为我们在旧代码库中有几个工厂。

更好的解决方案是在组合根中创建一个工厂,并使用注入的 IserviceProvider(或与 Lamar 一起使用 IContainer)。这是一个简单的解决方法。

考虑到我们的创建问题,在启动过程完成后创建我们的对象作为第一个控制器访问的延迟验证正常工作。

于 2022-01-28T22:44:00.690 回答