Created
May 16, 2012 12:34
-
-
Save haf/2710007 to your computer and use it in GitHub Desktop.
Windsor custom lifestyle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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