问题
I have IWindsorContaner which exists for the whole application lifetime. For Unittests it is possible to register mocks/stubs, etc. under their Type. When the test is finished and the fixture is disposed the registered components in forthe test are remove with a self created method called "Unregister".
Now, I want to update to the latest Castle version which is 3.0. According to the 3.0 release notes something like
public void Unregister(string contextName, string registrationName)
{
IWindsorContainer context = GetOrCreateContext(contextName);
context.Kernel.RemoveComponent(registrationName);
}
is not possible anymore, because the IKernel.RemoveComponent method has been removed. The description to fix this is not really sufficient ("Try utilizing IHandlerSelectors.").
A simplified version of the fixture I use for unittests:
public sealed class DependencyInjectionFixture : IDisposable
{
private Stack<Type> registeredTypes = new Stack<Type>();
// Registering of mocks/stubs, etc
public void RegisterSingleton<T>(T singleton, string objectName)
{
registeredTypes.Push(typeof(T));
IWindsorContainer context = GetOrCreateContext(contextName);
context.Register(Component.For(typeof(T))
.Named(objectName)
.Instance(singleton)
.LifeStyle.Singleton);
}
// Called when tests ends
public void Dispose()
{
IWindsorContainer context = GetOrCreateContext(contextName);
while (registeredTypes.Count > 0)
context.Kernel.RemoveComponent(CSApplicationContext.GetRegistrationNameFor(registeredTypes.Pop()));
}
}
How can I remove components with Castle 3.0?
回答1:
Instead of trying to remove all components, just create a new IWindsorContainer
and bind that to whatever GetOrCreateContext
is checking against. Then you'll have a fresh new container that has nothing bound to it.
回答2:
I know Im late to the game but I came up against this same issue. My problem was that due to the size of the application, first run of Castle Windsor was very slow (1s+) and to create a new context for each and every test was becoming onerous (600 tests, 5min wait time on Castle Windsor only)
I based my solution on How to remove component in Castle Windsor 3.0?
public class WindsorHandlerOverride : IHandlerSelector
{
private Dictionary<Type, object> definedTypeBehaviours;
public bool HasOpinionAbout(string key, Type service)
{
return definedTypeBehaviours.IsNotNullAndAny(t => t.Key == service);
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
var theValue = definedTypeBehaviours[service];
return new WindsorSimpleHandler {TheValue = theValue};
}
public void CleanUp()
{
definedTypeBehaviours = null;
}
public void OverrideBehaviour(Type type, object value)
{
if (definedTypeBehaviours == null)
{
definedTypeBehaviours = new Dictionary<Type, object>();
}
definedTypeBehaviours.Add(type, value);
}
}
and
public class WindsorSimpleHandler : IHandler
{
public object TheValue { get; set; }
public ComponentModel ComponentModel { get; set; }
public HandlerState CurrentState { get; set; }
public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model,
DependencyModel dependency)
{
return true;
}
public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model,
DependencyModel dependency)
{
return TheValue;
}
public object Resolve(CreationContext context)
{
return TheValue;
}...
Then wherever you set up windsor
WindsorOverrider = new WindsorHandlerOverride();
container.Kernel.AddHandlerSelector(WindsorOverrider);
And when you want to override castle windsor default behaviour in test
WindsorOverrider.OverrideBehaviour(typeof(IService), mock.Object);
And on test tear down call
WindsorOverrider.CleanUp();
来源:https://stackoverflow.com/questions/9501209/how-are-components-removed-with-castle-3-0