-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
Describe the bug
I am the author and maintainer of the LightInject DI library and we discovered something strange when upgrading one of our AspNetCore projects to netcoreapp2.2 and setting the compabilitylevel to 2_2
.
Then we started to see a StackoverflowException
at startup and as fun it is to debug these kind of exceptions, we still managed to track it down to Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Routing.EndpointOptions>
recursively being requested from the container causing the StackoverflowException
The object graphs are pretty deep here and we spent a day or so trying to figure out what was going on. I noticed that there are some IEnumerable<T>
being injected into the services down the object graph and then it suddenly hit me that this might be related to variance.
A couple of examples just to illustrate what this means.
public interface IFoo<out T> {}
public class FooWithBar : IFoo<Bar> {}
public class FooWithDerivedBar : IFoo<DerivedBar> {}
public class Bar {}
public class DerivedBar : Bar {}
When requesting a IFoo<Bar>
from LightInject, it will return 2 instances, FooWithBar
and FooWithDerivedBar
since they are compatible
For instance we can do this
IFoo<Bar> fb = new FooWithDerivedBar();
Note: Not trying to explain variance here. Just setting the scene.
This feature is very powerful and has worked great up until AspNetCore 2.2 where we now have to turn off support for variance in LightInject (through an option) in order to avoid the StackoverflowException
.
I know that this feature is not supported, at least not yet, in MS.DI, but it seems a little strange to require the DI adapter to disable support for variance.
I don't know of this was intentional, but it is maybe something to be aware of as it seems that proper support for open generics might find its way into MS.DI as well according to this PR.
We got around the problem by disabling variance in LightInject, but that also disables a very powerful feature. At the very least there should be a test for this over at the extensions repo that states this requirement. The requirement being that variance is not supported.
The best solution would be to fix this in AspNetCore so that it does not rely on non-variant behaviour.
To Reproduce
Steps to reproduce the behavior:
- Using this version of ASP.NET Core '2.2'
- dotnet new webapi
UseLightInject()
(using the LightInject.Microsoft.AspNetCore.Hosting package)- See error
Expected behavior
Not to throw a StackoverflowException