Castle Windsor:Startable Facility和“装饰模式”依赖项可能存在错误

时间:2010-10-21 17:12:42

标签: castle-windsor

当尝试注册依赖于其实现“装饰”相同服务接口的服务的可启动组件时,Castle无法解析可启动组件,声称无法解析依赖关系。奇怪的是,显式解析可启动组件按预期工作。我在Castle Windsor 2.5和2.5.1中都看到了这种行为。请参阅下面的NUnit测试用例:

更新

我发现我可以使用可启动的机制,但是我需要将IFoo实现者的注册分离到一个单独的container.Register()调用来注册可启动组件。 IFoo注册必须先发生。更有趣的是,如果我使用IWindsorInstaller安装组件,这工作。请参阅下面的其他测试用例:

更新

在单独的安装程序中安装IFoo实现者,在对container.Install()的单独调用中工作。通过将params []列表中的IWindsorInstaller包含到对container.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());
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

在HEAD中修复。将成为2.5.2版本的一部分。供将来参考,here's the bug report