mirror of https://github.com/AMT-Cheif/Stylet.git
Add singleton disposing
This commit is contained in:
parent
3246f5db29
commit
816df04f18
|
@ -43,7 +43,7 @@ namespace StyletIoC
|
|||
public Type Type { get { return this.creator.Type; } }
|
||||
|
||||
private readonly object generatorLock = new object();
|
||||
private Func<IRegistrationContext, object> generator;
|
||||
protected Func<IRegistrationContext, object> generator;
|
||||
|
||||
public RegistrationBase(ICreator creator)
|
||||
{
|
||||
|
@ -82,22 +82,39 @@ namespace StyletIoC
|
|||
internal class SingletonRegistration : RegistrationBase
|
||||
{
|
||||
private Expression instanceExpression;
|
||||
private object instance;
|
||||
private readonly IRegistrationContext parentContext;
|
||||
private bool disposed = false;
|
||||
|
||||
public SingletonRegistration(IRegistrationContext parentContext, ICreator creator) : base(creator)
|
||||
{
|
||||
this.parentContext = parentContext;
|
||||
this.parentContext.Disposing += (o, e) =>
|
||||
{
|
||||
this.disposed = true;
|
||||
|
||||
var disposable = this.instance as IDisposable;
|
||||
if (disposable != null)
|
||||
disposable.Dispose();
|
||||
|
||||
this.instance = null;
|
||||
this.instanceExpression = null;
|
||||
this.generator = null;
|
||||
};
|
||||
}
|
||||
|
||||
public override Expression GetInstanceExpression(ParameterExpression registrationContext)
|
||||
{
|
||||
if (this.disposed)
|
||||
throw new ObjectDisposedException(String.Format("Singleton registration for type {0}", this.Type.Description()));
|
||||
|
||||
if (this.instanceExpression != null)
|
||||
return this.instanceExpression;
|
||||
|
||||
var instance = Expression.Lambda<Func<IRegistrationContext, object>>(this.creator.GetInstanceExpression(registrationContext), registrationContext).Compile()(this.parentContext);
|
||||
this.instance = Expression.Lambda<Func<IRegistrationContext, object>>(this.creator.GetInstanceExpression(registrationContext), registrationContext).Compile()(this.parentContext);
|
||||
|
||||
// This expression yields the actual type of instance, not 'object'
|
||||
var instanceExpression = Expression.Constant(instance);
|
||||
var instanceExpression = Expression.Constant(this.instance);
|
||||
Interlocked.CompareExchange(ref this.instanceExpression, instanceExpression, null);
|
||||
return this.instanceExpression;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,11 @@ namespace StyletUnitTests.StyletIoC
|
|||
interface IValidator<T> { }
|
||||
class StringValidator : IValidator<string> { }
|
||||
class IntValidator : IValidator<int> { }
|
||||
class C5 : IDisposable
|
||||
{
|
||||
public bool Disposed;
|
||||
public void Dispose() { this.Disposed = true; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChildContainerCanAccessRegistrationsOnParent()
|
||||
|
@ -191,5 +196,37 @@ namespace StyletUnitTests.StyletIoC
|
|||
Assert.DoesNotThrow(() => child.Get<IValidator<int>>());
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => parent.Get<IValidator<int>>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ContainerDisposesItsSingletonsWhenRequested()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C5>().ToSelf().InSingletonScope();
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var c5 = parent.Get<C5>();
|
||||
Assert.False(c5.Disposed);
|
||||
|
||||
parent.Dispose();
|
||||
Assert.True(c5.Disposed);
|
||||
Assert.Throws<ObjectDisposedException>(() => parent.Get<C5>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DisposingContainerDoesNotDisposeParentSingletons()
|
||||
{
|
||||
var builder = new StyletIoCBuilder();
|
||||
builder.Bind<C5>().ToSelf().InSingletonScope();
|
||||
var parent = builder.BuildContainer();
|
||||
|
||||
var child = parent.CreateChildBuilder().BuildContainer();
|
||||
|
||||
// Make sure it actually gets built
|
||||
var c5 = parent.Get<C5>();
|
||||
|
||||
child.Dispose();
|
||||
|
||||
Assert.False(parent.Get<C5>().Disposed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue