При попытке зарегистрировать запускаемый компонент, который зависит от службы, реализация которой «украшает» тот же интерфейс службы, Castle не удается разрешить запускаемый компонент, утверждая, что зависимость не может быть разрешена. Как ни странно, явное разрешение запускаемого компонента работает, как и ожидалось. Я видел это поведение в Касл Виндзор 2.5 и 2.5.1. Пожалуйста, смотрите ниже тестовый пример NUnit:
UPDATE
Я обнаружил, что могу заставить работать механизм запуска, но мне нужно разделить регистрации разработчиков IFoo в отдельном вызове container.Register () от регистрации компонента запуска. Регистрация IFoo должна произойти в первую очередь. Еще интереснее то, что не работает, если я использую IWindsorInstaller для установки компонентов. Пожалуйста, посмотрите дополнительные тестовые случаи ниже:
UPDATE
Установка разработчиков IFoo в отдельном инсталляторе, в отдельном вызове container.Install () работает. Установка запускаемого компонента путем включения его IWindsorInstaller в список params [] в один вызов контейнера .Install () работает , а не , но установка его в отдельном вызове container.Install () работает. Я объединил все контрольные примеры в приведенный ниже фрагмент кода:
using System;
using Castle.Facilities.Startable;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using NUnit.Framework;
namespace Tests
{
[TestFixture]
public class TestProblemsWithStartableAndDecorators
{
/// <summary>
/// This test passes with the following output to the console:
///
/// foo decorator
/// typeof decorated : Foo
/// startable constructor
/// typeof foo : FooDecorator
///
/// </summary>
[Test]
public void TestUsingResolve()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Register(
Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>(),
Component.For<IGetStarted>().ImplementedBy<GetStarted>()
);
container.Resolve<IGetStarted>();
}
}
/// <summary>
/// This test should pass with the same output as the above test.
/// However, it fails with the following exeption:
///
/// Castle.MicroKernel.Handlers.HandlerException : Can't create component 'Tests.TestProblemsWithStartableAndDecorators+FooDecorator' as it has dependencies to be satisfied.
/// Tests.TestProblemsWithStartableAndDecorators+FooDecorator is waiting for the following dependencies:
///
/// Services:
/// - Tests.TestProblemsWithStartableAndDecorators+IFoo.
/// A dependency cannot be satisfied by itself, did you forget to add a parameter name to differentiate between the two dependencies?
///
/// Tests.TestProblemsWithStartableAndDecorators+foo is registered and is matching the required service, but cannot be resolved.
/// </summary>
[Test]
public void TestUsingStartable()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Register(
Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>(),
Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start()
);
}
}
public interface IFoo
{
}
public class Foo : IFoo
{
}
public class FooDecorator : IFoo
{
public FooDecorator(IFoo decorated)
{
Console.WriteLine("foo decorator");
Console.WriteLine(" typeof decorated : " + decorated.GetType().Name);
}
}
public interface IGetStarted
{
}
public class GetStarted : IGetStarted
{
public GetStarted(IFoo foo)
{
Console.WriteLine("startable constructor");
Console.WriteLine(" typeof foo : " + foo.GetType().Name);
}
}
// works
[Test]
public void TestUsingStartableWithSeparateRegistrations()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Register(Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>());
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
}
}
// fails
[Test]
public void TestUsingStartableWithSeparateRegistrationsRegisteringStartableFirst()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
container.Register(Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>());
}
}
// fails
[Test]
public void TestUsingStartableWithInstaller()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Install(new TestInstaller());
}
}
public class TestInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container.Register(Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>());
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
}
}
// works
[Test]
public void TestUsingStartableWithSeparateFooInstaller()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Install(new FooInstaller());
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
}
}
// fails
[Test]
public void TestUsingStartableWithSeparateInstallers()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Install(new FooInstaller(), new StartableInstaller());
}
}
// works
[Test]
public void TestUsingStartableWithSeparateCallsToInstall()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Install(new FooInstaller());
container.Install(new StartableInstaller());
}
}
public class FooInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container.Register(Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>());
}
}
public class StartableInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
}
}
}
}