Skip to content

Commit

Permalink
Fix dispose for scoped container.
Browse files Browse the repository at this point in the history
  • Loading branch information
byme8 committed Jul 23, 2024
1 parent 7dac137 commit c939a74
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 19 deletions.
27 changes: 17 additions & 10 deletions src/ZeroIoC.Core/ZeroIoCContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ namespace ZeroIoC
public abstract class ZeroIoCContainer : IZeroIoCResolver
{
protected readonly Dictionary<Type, IInstanceResolver> Resolvers = new Dictionary<Type, IInstanceResolver>();
protected readonly Dictionary<Type, IInstanceResolver> ScopedResolvers = new Dictionary<Type, IInstanceResolver>();

protected readonly Dictionary<Type, IInstanceResolver> ScopedResolvers =
new Dictionary<Type, IInstanceResolver>();

protected readonly bool Scoped;

Expand All @@ -34,7 +36,7 @@ public virtual IZeroIoCResolver Clone()
}

protected abstract void Bootstrap(IZeroIoCContainerBootstrapper bootstrapper);

public object Resolve(Type type)
{
if (Resolvers.TryGetValue(type, out var entry))
Expand All @@ -58,7 +60,7 @@ public object Resolve(Type type)
ExceptionHelper.ServiceIsNotRegistered(type.FullName);
return null;
}

public object Resolve(Type type, IOverrides overrides)
{
if (Resolvers.TryGetValue(type, out var entry))
Expand All @@ -83,7 +85,8 @@ public object Resolve(Type type, IOverrides overrides)
return null;
}

public void AddDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceType, Reuse reuse = Reuse.Transient)
public void AddDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceType,
Reuse reuse = Reuse.Transient)
{
switch (reuse)
{
Expand All @@ -100,13 +103,14 @@ public void AddDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceT
throw new ArgumentOutOfRangeException(nameof(reuse), reuse, null);
}
}

public void ReplaceDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceType, Reuse reuse = Reuse.Transient)

public void ReplaceDelegate(Func<IZeroIoCResolver, object> resolver, Type interfaceType,
Reuse reuse = Reuse.Transient)
{
switch (reuse)
{
case Reuse.Scoped:
ScopedResolvers[interfaceType] =new SingletonResolver(resolver);
ScopedResolvers[interfaceType] = new SingletonResolver(resolver);
break;
case Reuse.Singleton:
Resolvers[interfaceType] = new SingletonResolver(resolver);
Expand All @@ -123,7 +127,7 @@ public void AddInstance<TValue>(TValue value)
{
Resolvers.Add(typeof(TValue), new SingletonResolver(o => value));
}

public void ReplaceInstance<TValue>(TValue value)
{
Resolvers[typeof(TValue)] = new SingletonResolver(o => value);
Expand All @@ -144,9 +148,12 @@ public void Merge(ZeroIoCContainer container)

public void Dispose()
{
foreach (var resolver in Resolvers.Values)
if (!Scoped)
{
resolver.Dispose();
foreach (var resolver in Resolvers.Values)
{
resolver.Dispose();
}
}

foreach (var resolver in ScopedResolvers.Values)
Expand Down
27 changes: 18 additions & 9 deletions src/ZeroIoC.Tests/ScopedContainerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,17 @@ public async Task ServicesWithinTheScopeIsDisposed()
{
var project = await TestProject.Project.ApplyToProgram(@"
public interface IService : IDisposable
public class SingletonService : IDisposable
{
bool Disposed { get; set; }
public bool Disposed { get; set; }
public void Dispose()
{
Disposed = true;
}
}
public class Service : IService
public class Service : IDisposable
{
public bool Disposed { get; set; }
Expand All @@ -112,7 +117,8 @@ public partial class TestContainer : ZeroIoCContainer
{
protected override void Bootstrap(IZeroIoCContainerBootstrapper bootstrapper)
{
bootstrapper.AddScoped<IService, Service>();
bootstrapper.AddScoped<Service>();
bootstrapper.AddSingleton<SingletonService>();
}
}
");
Expand All @@ -121,20 +127,23 @@ protected override void Bootstrap(IZeroIoCContainerBootstrapper bootstrapper)

var assembly = await newProject.CompileToRealAssembly();
var containerType = assembly.GetType("TestProject.TestContainer");
var serviceType = assembly.GetType("TestProject.IService");
var serviceType = assembly.GetType("TestProject.Service");
var singletonServiceType = assembly.GetType("TestProject.SingletonService");

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

object service = null;
object singletonService = null;
using (var scoped = container.CreateScope())
{
service = scoped.Resolve(serviceType);
var initialValue = (bool)service.ReflectionGetValue("Disposed");
Assert.False((bool)service.ReflectionGetValue("Disposed"));

Assert.False(initialValue);
singletonService = scoped.Resolve(singletonServiceType);
Assert.False((bool)service.ReflectionGetValue("Disposed"));
}

var value = (bool)service.ReflectionGetValue("Disposed");
Assert.True(value);
Assert.True((bool)service.ReflectionGetValue("Disposed"));
Assert.False((bool)singletonService.ReflectionGetValue("Disposed"));
}
}

0 comments on commit c939a74

Please sign in to comment.