Closed BrandtWright closed 7 years ago
Actually, this library passes all tests in Microsoft.Extensions.DependencyInjection.Specification.Tests. So, I was trusting these tests and not used scoped before (I mostly use singleton and transients). Thank you for reporting it. I'll check this in a short time.
I could not repeat the problem.
I created a unit test: https://github.com/volosoft/castle-windsor-ms-adapter/commit/c81f543e851cf73b5716db0e2fedcf2d6ddc246b and it's passing.
I created a controller and some services to test in real AspNet Core application: https://github.com/aspnetboilerplate/aspnetboilerplate/commit/5cb3c4bc9e6faff8bba212d5cb29ee02594640c5
A test result:
_myTransientClass1.ScopedClass.Id = 859c35b9674b429985ff56f7e80da00f; _myTransientClass2.ScopedClass.Id = 859c35b9674b429985ff56f7e80da00f
As you see, they are same, so a scoped class is instantiated once per request.
Can you create an empty application to demonstrate it and share with me if possible?
Sure. I'll put that together now and share it when done.
I have attached a solution which demonstrates the problem. Injection into controller constructors and even nested dependencies works fine. However, anything that uses a call to container.resolve
Do you have any advise/suggestions/workarounds to deal with this behavior?
Hi,
You should not directly resolve from IWindsorContainer. You should resolve from IServiceProvider. So, change your code like that:
using Microsoft.Extensions.DependencyInjection;
...
public class NaivePerWebRequestServiceFactory
{
private readonly IServiceProvider _serviceProvider;
public NaivePerWebRequestServiceFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IPerWebRequestService GetService()
{
return _serviceProvider.GetService<IPerWebRequestService>(); // returns transient instance
// despite the fact thatIperWebRequest
// was registerd as MsScoped...
}
}
Because IWindsorContainer does not know about current request, but IServiceProvider
does know http request context, since a dedicated service provider is created per web request (by ASP.NET Core).
So... do i understand correctly that when i register scoped component to IServiceCollection like this:
services.AddScoped<IOperationScoped, Operation>();
Then i cant use property resolver through castle windsor?
public class OperationsController : Controller
{
public IOperationScoped ScopedOperation { get; set; }
}
Instead i have to resolve IOperationScoped through IServiceCollection? Thats ugly
You can use property injection if you use AddControllersAsServices() (like .AddMvc().AddControllersAsServices()).
Yep.. that did the trick!
Thanks!
When registering components as scoped (which is equivalent to perwebrequest) with aspnet core framework via the configureservices(...) method in the startup class things seem to work fine until I request a scoped instance from classes registered with the windsor container.
If I register IFoo with aspnet core via configureservices(...) and then request an instance of it from multiple types that were registered with the windsor container I get a new instance of IFoo in each class that requests an instance of IFoo even though this all happens as part of the same web request.
This is a trivial example but consider trying to implement a unit or work pattern for DB integration and not being able to inject the same instance of the unit of work in multiple types registered via windsor for a single web request.
Am I doing something wrong? Has anyone had any luck with this?