Skip to content

Commit

Permalink
Merge pull request #38 from volosoft/singleton-service-scope-factory
Browse files Browse the repository at this point in the history
Change IServiceScopeFactory lifetime to singleton.
  • Loading branch information
maliming authored Aug 18, 2020
2 parents dd1a284 + 6b185fb commit 07fafa7
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 21 deletions.
26 changes: 26 additions & 0 deletions src/Castle.Windsor.MsDependencyInjection.Tests/TestClassFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Concurrent;
using Castle.Windsor.MsDependencyInjection.Tests.TestClasses;
using Microsoft.Extensions.DependencyInjection;

namespace Castle.Windsor.MsDependencyInjection.Tests
{
public class MyTestClass3Factory
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ConcurrentDictionary<string, MyTestClass3> _services = new ConcurrentDictionary<string, MyTestClass3>();

public MyTestClass3Factory(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}

public MyTestClass3 Create(string name)
{
return _services.GetOrAdd(name, s =>
{
var scope = _scopeFactory.CreateScope(); // The scope will not dispose, by design.
return scope.ServiceProvider.GetRequiredService<MyTestClass3>();
});
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Castle.MicroKernel.Registration;
using Castle.Windsor.MsDependencyInjection.Tests.TestClasses;
Expand All @@ -28,7 +27,41 @@ protected override IServiceProvider CreateServiceProvider(IServiceCollection ser
return WindsorRegistrationHelper.CreateServiceProvider(
_windsorContainer,
serviceCollection
);
);
}

[Fact]
public void SingletonServiceShouldResolveServicesFromTheRootServiceScopeFactory()
{
var collection = new ServiceCollection();
collection.AddTransient<MyTestClass3>();
collection.AddSingleton<MyTestClass3Factory>();

var serviceProvider = CreateServiceProvider(collection);

MyTestClass3 instanceA1;

using (var scope1 = serviceProvider.CreateScope())
{
var factory = scope1.ServiceProvider.GetRequiredService<MyTestClass3Factory>();
instanceA1 = factory.Create("A");
instanceA1.IsDisposed.ShouldBeFalse();
}

instanceA1.IsDisposed.ShouldBeFalse();

MyTestClass3 instanceA2;

using (var scope2 = serviceProvider.CreateScope())
{
var factory = scope2.ServiceProvider.GetRequiredService<MyTestClass3Factory>();
instanceA2 = factory.Create("A");
instanceA2.IsDisposed.ShouldBeFalse();
}

instanceA2.IsDisposed.ShouldBeFalse();

Assert.Equal(instanceA1, instanceA2);
}

[Fact]
Expand All @@ -40,7 +73,8 @@ public void ResolvingFromScopeAndReleasingShouldWorkForWindsorTransients()

var serviceProvider = CreateServiceProvider(collection);

serviceProvider.GetService<IWindsorContainer>().Register(Component.For<MyTestClass1>().LifestyleTransient());
serviceProvider.GetService<IWindsorContainer>()
.Register(Component.For<MyTestClass1>().LifestyleTransient());

var scopeFactory = serviceProvider.GetService<IServiceScopeFactory>();
IServiceProvider scopeServiceProvider;
Expand Down Expand Up @@ -71,7 +105,8 @@ public void ResolvingFromContainerShouldWork()

var serviceProvider = CreateServiceProvider(collection);

serviceProvider.GetService<IWindsorContainer>().Register(Component.For<MyTestClass1>().LifestyleTransient());
serviceProvider.GetService<IWindsorContainer>()
.Register(Component.For<MyTestClass1>().LifestyleTransient());

var testObj1 = serviceProvider.GetService<IWindsorContainer>().Resolve<MyTestClass1>();
testObj1.IsDisposed.ShouldBeFalse();
Expand All @@ -86,14 +121,14 @@ public void ResolvingFromContainerShouldWork()
[Fact]
public void ResolvingFromScopeShouldWorkForWindsorTransients()
{

var collection = new ServiceCollection();
collection.AddTransient<MyTestClass1>();
collection.AddScoped<MyTestClass2>();

var serviceProvider = CreateServiceProvider(collection);

serviceProvider.GetService<IWindsorContainer>().Register(Component.For<MyTestClass3>().LifestyleTransient());
serviceProvider.GetService<IWindsorContainer>()
.Register(Component.For<MyTestClass3>().LifestyleTransient());

var scopeFactory = serviceProvider.GetService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
Expand Down Expand Up @@ -225,7 +260,7 @@ public void Should_Resolve_Registered_Enumerable()
{
var collection = new ServiceCollection();

collection.AddSingleton((IEnumerable<MyTestClass3>)new List<MyTestClass3>
collection.AddSingleton((IEnumerable<MyTestClass3>) new List<MyTestClass3>
{
new MyTestClass3(),
new MyTestClass3(),
Expand Down Expand Up @@ -284,16 +319,16 @@ public void FactoryServicesAreCreatedAsPartOfCreatingObjectGraph_2()
{
var services = new ServiceCollection();
services.AddTransient<IFakeService, FakeService>();
services.AddTransient<IFactoryService>((Func<IServiceProvider, IFactoryService>)(p =>
services.AddTransient<IFactoryService>((Func<IServiceProvider, IFactoryService>) (p =>
{
IFakeService service = p.GetService<IFakeService>();
return (IFactoryService)new TransientFactoryService()
return (IFactoryService) new TransientFactoryService()
{
FakeService = service,
Value = 42
};
}));
services.AddScoped<ScopedFactoryService>((Func<IServiceProvider, ScopedFactoryService>)(p =>
services.AddScoped<ScopedFactoryService>((Func<IServiceProvider, ScopedFactoryService>) (p =>
{
IFakeService service = p.GetService<IFakeService>();
return new ScopedFactoryService()
Expand All @@ -302,20 +337,20 @@ public void FactoryServicesAreCreatedAsPartOfCreatingObjectGraph_2()
};
}));
services.AddTransient<ServiceAcceptingFactoryService>();
IServiceProvider serviceProvider = this.CreateServiceProvider((IServiceCollection)services);
IServiceProvider serviceProvider = this.CreateServiceProvider((IServiceCollection) services);
using (var scope = serviceProvider.CreateScope())
{
serviceProvider = scope.ServiceProvider;

ServiceAcceptingFactoryService service1 = serviceProvider.GetService<ServiceAcceptingFactoryService>();
ServiceAcceptingFactoryService service2 = serviceProvider.GetService<ServiceAcceptingFactoryService>();
Assert.Equal<int>(42, service1.TransientService.Value);
Assert.NotNull((object)service1.TransientService.FakeService);
Assert.NotNull((object) service1.TransientService.FakeService);
Assert.Equal<int>(42, service2.TransientService.Value);
Assert.NotNull((object)service2.TransientService.FakeService);
Assert.NotNull((object)service1.ScopedService.FakeService);
Assert.NotSame((object)service1.TransientService, (object)service2.TransientService);
Assert.Same((object)service1.ScopedService, (object)service2.ScopedService);
Assert.NotNull((object) service2.TransientService.FakeService);
Assert.NotNull((object) service1.ScopedService.FakeService);
Assert.NotSame((object) service1.TransientService, (object) service2.TransientService);
Assert.Same((object) service1.ScopedService, (object) service2.ScopedService);
}
}

Expand Down Expand Up @@ -374,7 +409,8 @@ public void Resolving_Named_Component_With_ServiceOverride()

windsorContainer.Register(
Component.For<MyTestClass3>().Named("CustomTestClass"),
Component.For<MyTestClass2>().ImplementedBy<MyTestClass2>().DependsOn(ServiceOverride.ForKey("myTestClass3").Eq("CustomTestClass"))
Component.For<MyTestClass2>().ImplementedBy<MyTestClass2>()
.DependsOn(ServiceOverride.ForKey("myTestClass3").Eq("CustomTestClass"))
);

var test1 = serviceProvider.GetService<MyTestClass2>();
Expand All @@ -386,4 +422,4 @@ public void Dispose()
Assert.Null(MsLifetimeScope.Current);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Castle.Windsor.MsDependencyInjection
public static class WindsorRegistrationHelper
{
/// <summary>
/// Adds all given services from <see cref="Microsoft.Extensions.DependencyInjection"/>
/// Adds all given services from <see cref="Microsoft.Extensions.DependencyInjection"/>
/// to the Castle Windsor container.
/// </summary>
/// <returns>A Castle Windsor service provider.</returns>
Expand Down Expand Up @@ -64,7 +64,7 @@ private static void AddBaseServices(IWindsorContainer container)
container.Register(
Component.For<IServiceScopeFactory>()
.ImplementedBy<WindsorServiceScopeFactory>()
.LifestyleTransient()
.LifestyleSingleton()
);
}

Expand Down Expand Up @@ -173,4 +173,4 @@ private static ComponentRegistration<object> ConfigureLifecycle(this ComponentRe
return registrationBuilder;
}
}
}
}

0 comments on commit 07fafa7

Please sign in to comment.