1

We have migrated from a windows Framework 4.7 application to .NET 6.0. Lamar is added for Dependency Injection. We are trying to finalize a refactor to the latest "one-file" program.cs but are getting unexpected System.ObjectDisposedException: 'Cannot access a disposed object'. In all cases, the error is against a Func<T> during object creation.

All our tests are running correctly using the same environment, except to start the tests we (a) create the DI container and (b) use the container to create an object that loads the singletons (from MongoDB):

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

In the program.cs, we configure the container, but do not get to see it created, or access it inside program.cs. Instead we create HomeService from IServiceProvider during the first use of a controller. Here we were trying to limit the lifecyle scope during creation:

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

For test, we use the same loading steps, except for adding controllers/mvc, of course (i.e. NOT using builder.Services.AddControllers(); and builder.Services.AddMvc() for (integration) testing).

We have tried a lot of different things, like creating our object independently to the startup, but that did not align the singletons. We can get functionality by using static instead, but then we lose dynamic change access.

Some great tips like Resolving instances with ASP.NET Core DI from within ConfigureServices and https://andrewlock.net/exploring-dotnet-6-part-10-new-dependency-injection-features-in-dotnet-6/ but I can't see the specific example to get the live container just after initial creation.

Is it possible that the issue is just the difference between the lifecycle management of the new .NET DI implementation? As this is configuration at the composition root, if we can configure as per our testing approach, it should solve our problem. Other solutions welcome!

johnball
  • 31
  • 4

1 Answers1

1

The problem 'Cannot access a disposed object' was being caused by a lifecycle mismatch between retained context and the controller access. The code retained a handle on the state object, that had a handle on the factory using FUNC. As we did not configure the Func as anything, it was transient during the controller graph creation, and so was disposed when the controller request ended.

To solve, we tried registering ALL of the FUNC, per How to use Func<T> in built-in dependency injection which was a large task as we had a few factories throughout an old codebase.

The better solution was to create a factory in the composition root, and use an injected IserviceProvider (or with Lamar an IContainer). This is a simple workaround.

With our creation concern, the creation of our object after the completion of the startup process is working correctly as a lazy validation of the first controller access.

johnball
  • 31
  • 4