Skip to content

Instantly share code, notes, and snippets.

@haf
Created May 16, 2012 12:34
Show Gist options
  • Save haf/2710007 to your computer and use it in GitHub Desktop.
Save haf/2710007 to your computer and use it in GitHub Desktop.
Windsor custom lifestyle
[Explicit("For use on mailing list")]
public class WindsorNotDisposingTest
{
class MyDisposable
: IDisposable
{
bool _wasDisposed;
public bool WasDisposed
{
get { return _wasDisposed; }
}
void IDisposable.Dispose()
{
_wasDisposed = true;
}
}
[Test]
public void doesnt_dispose()
{
var waitForCall = new ManualResetEventSlim(false);
WeakReference reff = null;
var wc = new WindsorContainer();
wc.Register(Component.For<MyDisposable>()
.UsingBackgroundFactoryMethod(() =>
{
var instance = new MyDisposable();
reff = new WeakReference(instance, true);
waitForCall.Set();
return instance;
}));
waitForCall.Wait();
Assert.IsNotNull(reff);
wc.Dispose();
GC.Collect();
Assert.That(reff.IsAlive, "because no GC runs while it referenced on the same stack");
Assert.That(((MyDisposable)reff.Target).WasDisposed, Is.False,
"because it's still referenced by this method and Windsor isn't deterministically disposing it");
}
[Test]
public void disposes_with_lifestyle_manager()
{
var waitForCall = new ManualResetEventSlim(false);
WeakReference reff = null;
var wc = new WindsorContainer();
wc.Register(
Component.For<MyDisposable>()
.LifestyleCustom<BackgroundLifestyle<SingletonLifestyleManager>>()
.UsingBackgroundFactoryMethod(() =>
{
var instance = new MyDisposable();
reff = new WeakReference(instance, true);
waitForCall.Set();
return instance;
}));
waitForCall.Wait();
Assert.IsNotNull(reff);
wc.Dispose();
if (reff.IsAlive)
Assert.That(((MyDisposable)reff.Target).WasDisposed, Is.True,
"because it's still referenced by this method and Windsor isn't deterministically disposing it");
else
Console.WriteLine("GC beat me to it!");
GC.Collect();
Assert.That(reff.IsAlive, Is.False, "because the lifestyle manager should have disposed it and it's not referenced anymore");
}
}
class BackgroundLifestyle<T>
: ILifestyleManager
where T : ILifestyleManager, new()
{
T _inner;
IComponentActivator _activator;
bool _resolvedOnce;
public BackgroundLifestyle()
{
_inner = new T();
}
public void Init(IComponentActivator componentActivator, IKernel kernel, ComponentModel model)
{
_inner.Init(componentActivator, kernel, model);
_activator = componentActivator;
}
public object Resolve(CreationContext context, IReleasePolicy releasePolicy)
{
_resolvedOnce = true;
return _inner.Resolve(context, releasePolicy);
}
public bool Release(object instance)
{
return _inner.Release(instance);
}
public void Dispose()
{
if (!_resolvedOnce)
{
var context = CreationContext.CreateEmpty();
using (context.EnterResolutionContext(context.Handler, true))
{
/* On line below:
* Debug|2012-05-17 11:30:28.4281 +02:00|15|Installers.WindsorEx|thread pool before initialization executing
* Debug|2012-05-17 11:30:28.4281 +02:00|15|Installers.WindsorEx|thread pool factory starting
* Debug|2012-05-17 11:30:28.4281 +02:00|15|Installers.WindsorEx|thread pool factory done
* Test 'Tests.WindsorNotDisposingTest.disposes_with_lifestyle_manager' failed: System.NullReferenceException : Object reference not set to an instance of an object.
* at Castle.MicroKernel.Context.CreationContext.CreateBurden(IComponentActivator componentActivator, Boolean trackedExternally)
* WindsorNotDisposingTest.cs(138,0): at Tests.BackgroundLifestyle`1.Dispose()
* at Castle.MicroKernel.Handlers.DefaultHandler.Dispose()
* at Castle.MicroKernel.DefaultKernel.DisposeHandler(IHandler handler)
* at Castle.MicroKernel.DefaultKernel.DisposeHandlers()
* at Castle.MicroKernel.DefaultKernel.Dispose()
* at Castle.Windsor.WindsorContainer.Dispose()
* WindsorNotDisposingTest.cs(83,0): at Tests.WindsorNotDisposingTest.disposes_with_lifestyle_manager() */
var burden = context.CreateBurden(_activator, false);
var instance = _activator.Create(context, burden);
_activator.Destroy(instance);
burden.Release();
}
}
_inner.Dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment