mirror of
https://github.com/AlexMacocian/Slim.git
synced 2026-07-15 15:19:59 +00:00
Scoped ServiceManager calls original ServiceManager when resolving singletons
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Macocian Alexandru Victor
|
||||
Copyright (c) 2021 Macocian Alexandru Victor
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Slim.Tests.Models;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Slim.Tests
|
||||
{
|
||||
[TestClass]
|
||||
public sealed class MemoryLeakTests
|
||||
{
|
||||
private const int ScopesCount = 10000;
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateAndReleaseScopesDisposeManagerGCCollects()
|
||||
{
|
||||
var di = new ServiceManager();
|
||||
di.RegisterSingleton<IIndependentService, IndependentService>();
|
||||
di.RegisterScoped<IDependentService, DependentService>();
|
||||
var independentService = di.GetService<IIndependentService>();
|
||||
var dependentService = di.GetService<IDependentService>();
|
||||
|
||||
var weakRefs = new WeakReference[ScopesCount];
|
||||
for (int i = 0; i < ScopesCount; i++)
|
||||
{
|
||||
var scopedDi = di.CreateScope();
|
||||
weakRefs[i] = new WeakReference(scopedDi);
|
||||
var scopedDependentService = scopedDi.GetService<IDependentService>();
|
||||
scopedDependentService.Should().NotBeNull();
|
||||
scopedDependentService.Should().NotBe(dependentService);
|
||||
scopedDependentService.IndependentService.Should().NotBeNull();
|
||||
scopedDependentService.IndependentService.Should().Be(independentService);
|
||||
}
|
||||
|
||||
await Task.Delay(1500);
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
foreach(var weakRef in weakRefs)
|
||||
{
|
||||
weakRef.IsAlive.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -429,9 +429,9 @@ namespace Slim.Tests
|
||||
{
|
||||
var di = new ServiceManager();
|
||||
di.RegisterSingleton<IIndependentService, IndependentService>();
|
||||
var scopedDi = di.CreateScope();
|
||||
|
||||
var service = di.GetService<IIndependentService>();
|
||||
var scopedDi = di.CreateScope();
|
||||
var scopedService = scopedDi.GetService<IIndependentService>();
|
||||
|
||||
service.Should().Be(scopedService);
|
||||
|
||||
+18
-4
@@ -673,7 +673,7 @@ namespace Slim
|
||||
var dictionary = new Dictionary<Type, object>();
|
||||
foreach (var kvp in this.Instances)
|
||||
{
|
||||
if (this.InterfaceMapping.First(s => s.Value.Item1 == kvp.Key).Value.Item2 is not Lifetime.Scoped)
|
||||
if (this.InterfaceMapping.First(s => s.Value.Item1 == kvp.Key).Value.Item2 is Lifetime.Singleton)
|
||||
{
|
||||
dictionary.Add(kvp.Key, kvp.Value);
|
||||
}
|
||||
@@ -687,8 +687,22 @@ namespace Slim
|
||||
var factories = new Dictionary<Type, Delegate>(this.Factories);
|
||||
var exceptionHandlers = new Dictionary<Type, Delegate>(this.ExceptionHandlers);
|
||||
var resolvers = new List<IDependencyResolver>(this.Resolvers);
|
||||
var singletons = this.GetSingletons();
|
||||
return new ServiceManager(interfaceMapping, singletons, factories, exceptionHandlers, resolvers);
|
||||
/*
|
||||
* For singletons, create a factory in scoped service manager that should call this manager
|
||||
* to retrieve the singleton.
|
||||
* This means that if the singleton has not yet been created in this service manager,
|
||||
* the scoped service manager will not create a new one but instead ask the original service manager to
|
||||
* create the singleton instead.
|
||||
*/
|
||||
foreach (var kvp in this.InterfaceMapping)
|
||||
{
|
||||
if (kvp.Value.Item2 is Lifetime.Singleton)
|
||||
{
|
||||
factories[kvp.Key] = new Func<IServiceProvider, object>((_) => this.PrepareAndGetService(kvp.Key));
|
||||
}
|
||||
}
|
||||
|
||||
return new ServiceManager(interfaceMapping, new Dictionary<Type, object>(), factories, exceptionHandlers, resolvers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -8,10 +8,10 @@
|
||||
<Company />
|
||||
<Product></Product>
|
||||
<Description>Service lifetime management and dependency injection framework.</Description>
|
||||
<AssemblyVersion>1.4.2.0</AssemblyVersion>
|
||||
<FileVersion>1.4.2.0</FileVersion>
|
||||
<AssemblyVersion>1.4.3.0</AssemblyVersion>
|
||||
<FileVersion>1.4.3.0</FileVersion>
|
||||
<PackageProjectUrl>https://github.com/AlexMacocian/Slim</PackageProjectUrl>
|
||||
<Version>1.4.2</Version>
|
||||
<Version>1.4.3</Version>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
|
||||
Reference in New Issue
Block a user