Skip to content

Commit c939a74

Browse files
committed
Fix dispose for scoped container.
1 parent 7dac137 commit c939a74

File tree

2 files changed

+35
-19
lines changed

2 files changed

+35
-19
lines changed

src/ZeroIoC.Core/ZeroIoCContainer.cs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ namespace ZeroIoC
77
public abstract class ZeroIoCContainer : IZeroIoCResolver
88
{
99
protected readonly Dictionary<Type, IInstanceResolver> Resolvers = new Dictionary<Type, IInstanceResolver>();
10-
protected readonly Dictionary<Type, IInstanceResolver> ScopedResolvers = new Dictionary<Type, IInstanceResolver>();
10+
11+
protected readonly Dictionary<Type, IInstanceResolver> ScopedResolvers =
12+
new Dictionary<Type, IInstanceResolver>();
1113

1214
protected readonly bool Scoped;
1315

@@ -34,7 +36,7 @@ public virtual IZeroIoCResolver Clone()
3436
}
3537

3638
protected abstract void Bootstrap(IZeroIoCContainerBootstrapper bootstrapper);
37-
39+
3840
public object Resolve(Type type)
3941
{
4042
if (Resolvers.TryGetValue(type, out var entry))
@@ -58,7 +60,7 @@ public object Resolve(Type type)
5860
ExceptionHelper.ServiceIsNotRegistered(type.FullName);
5961
return null;
6062
}
61-
63+
6264
public object Resolve(Type type, IOverrides overrides)
6365
{
6466
if (Resolvers.TryGetValue(type, out var entry))
@@ -83,7 +85,8 @@ public object Resolve(Type type, IOverrides overrides)
8385
return null;
8486
}
8587

86-
public void AddDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceType, Reuse reuse = Reuse.Transient)
88+
public void AddDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceType,
89+
Reuse reuse = Reuse.Transient)
8790
{
8891
switch (reuse)
8992
{
@@ -100,13 +103,14 @@ public void AddDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceT
100103
throw new ArgumentOutOfRangeException(nameof(reuse), reuse, null);
101104
}
102105
}
103-
104-
public void ReplaceDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceType, Reuse reuse = Reuse.Transient)
106+
107+
public void ReplaceDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceType,
108+
Reuse reuse = Reuse.Transient)
105109
{
106110
switch (reuse)
107111
{
108112
case Reuse.Scoped:
109-
ScopedResolvers[interfaceType] =new SingletonResolver(resolver);
113+
ScopedResolvers[interfaceType] = new SingletonResolver(resolver);
110114
break;
111115
case Reuse.Singleton:
112116
Resolvers[interfaceType] = new SingletonResolver(resolver);
@@ -123,7 +127,7 @@ public void AddInstance<TValue>(TValue value)
123127
{
124128
Resolvers.Add(typeof(TValue), new SingletonResolver(o => value));
125129
}
126-
130+
127131
public void ReplaceInstance<TValue>(TValue value)
128132
{
129133
Resolvers[typeof(TValue)] = new SingletonResolver(o => value);
@@ -144,9 +148,12 @@ public void Merge(ZeroIoCContainer container)
144148

145149
public void Dispose()
146150
{
147-
foreach (var resolver in Resolvers.Values)
151+
if (!Scoped)
148152
{
149-
resolver.Dispose();
153+
foreach (var resolver in Resolvers.Values)
154+
{
155+
resolver.Dispose();
156+
}
150157
}
151158

152159
foreach (var resolver in ScopedResolvers.Values)

src/ZeroIoC.Tests/ScopedContainerTest.cs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,17 @@ public async Task ServicesWithinTheScopeIsDisposed()
9393
{
9494
var project = await TestProject.Project.ApplyToProgram(@"
9595
96-
public interface IService : IDisposable
96+
public class SingletonService : IDisposable
9797
{
98-
bool Disposed { get; set; }
98+
public bool Disposed { get; set; }
99+
100+
public void Dispose()
101+
{
102+
Disposed = true;
103+
}
99104
}
100105
101-
public class Service : IService
106+
public class Service : IDisposable
102107
{
103108
public bool Disposed { get; set; }
104109
@@ -112,7 +117,8 @@ public partial class TestContainer : ZeroIoCContainer
112117
{
113118
protected override void Bootstrap(IZeroIoCContainerBootstrapper bootstrapper)
114119
{
115-
bootstrapper.AddScoped<IService, Service>();
120+
bootstrapper.AddScoped<Service>();
121+
bootstrapper.AddSingleton<SingletonService>();
116122
}
117123
}
118124
");
@@ -121,20 +127,23 @@ protected override void Bootstrap(IZeroIoCContainerBootstrapper bootstrapper)
121127

122128
var assembly = await newProject.CompileToRealAssembly();
123129
var containerType = assembly.GetType("TestProject.TestContainer");
124-
var serviceType = assembly.GetType("TestProject.IService");
130+
var serviceType = assembly.GetType("TestProject.Service");
131+
var singletonServiceType = assembly.GetType("TestProject.SingletonService");
125132

126133
var container = (IZeroIoCResolver)Activator.CreateInstance(containerType);
127134

128135
object service = null;
136+
object singletonService = null;
129137
using (var scoped = container.CreateScope())
130138
{
131139
service = scoped.Resolve(serviceType);
132-
var initialValue = (bool)service.ReflectionGetValue("Disposed");
140+
Assert.False((bool)service.ReflectionGetValue("Disposed"));
133141

134-
Assert.False(initialValue);
142+
singletonService = scoped.Resolve(singletonServiceType);
143+
Assert.False((bool)service.ReflectionGetValue("Disposed"));
135144
}
136145

137-
var value = (bool)service.ReflectionGetValue("Disposed");
138-
Assert.True(value);
146+
Assert.True((bool)service.ReflectionGetValue("Disposed"));
147+
Assert.False((bool)singletonService.ReflectionGetValue("Disposed"));
139148
}
140149
}

0 commit comments

Comments
 (0)