It''s not so much when to register the components that causes an issue
but when to register the facilities.  As long as I don't try add or
override existing components in castle config file code based
registration is fine, but if I want the user to be able to replace
implementations using the config file things start to fall apart.
Here are some methods I've tried with no success.

castle.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <facilities>
        <facility id="testfacility">
            <assemblies>
                <assembly>SomeAssembly</assembly>
            </assemblies>
        </facility>
    </facilities>
    <components>
        <component id="somecomponent"
service="Container.Tests.ISomeComponent, Container.Tests"
type="Container.Tests.SomeSpecializedComponent, Container.Tests"/>
    </components>
</configuration>

TestFacilityFixture.cs

namespace Container.Tests
{
    interface ISomeComponent { }
    public class SomeComponent : ISomeComponent { }
    public class SomeSpecializedComponent : SomeComponent { }

    public class TestFacility : AbstractFacility
    {
        public static IList<string> RegisteredComponents;
        public static bool ConfigurationAvailable;

        protected override void Init()
        {
            ConfigurationAvailable = FacilityConfig != null &&
FacilityConfig.Children["assemblies"] != null;
            Kernel.ComponentRegistered += Kernel_ComponentRegistered;
        }

        void Kernel_ComponentRegistered(string key,
Castle.MicroKernel.IHandler handler)
        {
            RegisteredComponents.Add(key);
        }
    }

    [TestFixture]
    public class TestFacilityFixture
    {
        const string ConfigFile = "castle-facility.config";

        [SetUp]
        public void SetUp()
        {
            TestFacility.ConfigurationAvailable = false;
            TestFacility.RegisteredComponents = new List<string>();
        }
        static void VerifyDesiredState(IWindsorContainer container)
        {
            Assert.That(TestFacility.ConfigurationAvailable, Is.True,
"configuration settings were not available");
            Assert.That(TestFacility.RegisteredComponents,
Has.Member("somecomponent"), "Facility was not notified of the
component's registration");
            Assert.That(container.Resolve<ISomeComponent>(),
Is.InstanceOfType(typeof(SomeSpecializedComponent)), "Expecting
instance of SomeSpecializedComponent");
        }

        [Test]
        //FAILS:
        // most examples I've seen register facilities and components
in constructor after config is parsed
        // but faicilities added after config are not notified when
components are registered
        public void TestConstructorInitialization()
        {
            var container = new TestContainer(new XmlInterpreter(ConfigFile));
            VerifyDesiredState(container);
        }
        [Test]
        //FAILS:
        // if facilities added before parsing configuration the
facility configuration settings are not available
        public void TestInstallStrategy()
        {
            var container = new TestContainer();
            container.RegisterFacilities();
            container.Install(Configuration.FromXmlFile(ConfigFile));
            container.RegisterComponents();

            VerifyDesiredState(container);
        }
        [Test]
        //FAILS:
        // Installer is run during creation even though no config file
has been specified yet
        public void TestSpecializedInstallerStrategy()
        {
            var container = new TestContainer(new DefaultKernel(), new
SpecializedComponentInstaller());
            container.Install(Configuration.FromXmlFile(ConfigFile));
            container.RegisterComponents();
            VerifyDesiredState(container);
        }
        [Test]
        //FAILS:
        // Seems that the config file settings are not merged
        public void TestAddFacilityToConfigurationStor()
        {
            var configStore = new DefaultConfigurationStore();
            var facilityTypeInfo = new MutableConfiguration("facility");
            facilityTypeInfo.Attribute("id", "testfacility");
            facilityTypeInfo.Attribute("type",
typeof(TestFacility).AssemblyQualifiedName);
            configStore.AddFacilityConfiguration("testfacility",
facilityTypeInfo);

            var container = new TestContainer(configStore);
            container.Install(Configuration.FromXmlFile(ConfigFile));
            container.RegisterComponents();
            VerifyDesiredState(container);
        }
    }

    public class TestContainer : WindsorContainer
    {
        public TestContainer() { }
        public TestContainer(IKernel kernel, IComponentsInstaller
installer) : base(kernel, installer) { }
        public TestContainer(IConfigurationStore configurationStore) :
base(configurationStore) { }

        public TestContainer(IConfigurationInterpreter interpreter) :
base(interpreter)
        {
            RegisterFacilities();
            RegisterComponents();
        }


        public void RegisterFacilities()
        {
            if(Kernel.GetFacilities().Count(t=>t is TestFacility) ==
0) AddFacility<TestFacility>("testfacility");
        }
        public void RegisterComponents()
        {
            if(!Kernel.HasComponent("somecomponent"))
            {

Register(Component.For<ISomeComponent>().ImplementedBy<SomeComponent>().Named("somecomponent"));
            }
            //....
        }


    }

    class SpecializedComponentInstaller : DefaultComponentInstaller
    {
        protected override void
SetUpFacilities(Castle.Core.Configuration.IConfiguration[]
configurations, IWindsorContainer container)
        {
            base.SetUpFacilities(configurations, container);
            if (container.Kernel.GetFacilities().Count(t => t is
TestFacility) == 0)
container.AddFacility<TestFacility>("testfacility");

        }
    }
}


If you specify the facility type rather than just id in config file
then all tests pass. (<facility id="testfacility"
type="Container.Tests.TestFacility, Container.Tests">)
So if I want to override any services in the config file it seems I
need to register the facility in the config file rather than in code.
The best alternative I can think of is not to use the component type
attribute to override existing services but instead to add an element
in the facility configuration like this I guess:
<somecomponent>Container.Tests.SomeSpecializedComponent,
Container.Tests</somecomponent>


Thoughts?

- Kurt

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Castle Project Users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/castle-project-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to