From 847103ef850745f0dc60d0da2fb11fe541570446 Mon Sep 17 00:00:00 2001 From: cneuwirt Date: Tue, 11 Mar 2008 15:27:40 +0000 Subject: [PATCH] Added generalized configuration support to ComponentRegistration besides parameters. These configuration are usually toplevel attributes or children than are used by facilities. git-svn-id: https://svn.castleproject.org/svn/castle/trunk@4881 73e77b4c-caa6-f847-a29a-24ab75ae54b6 --- .../Registration/ComponentRegistrationTestCase.cs | 29 ++- .../Castle.MicroKernel-vs2008.csproj | 2 + .../Registration/ComponentRegistration.cs | 85 +++++-- .../Registration/Configuration.cs | 275 +++++++++++++++++++++ .../Registration/ConfigurationDescriptor.cs | 36 +++ .../Castle.MicroKernel/Registration/Parameter.cs | 4 + InversionOfControl/Changes.txt | 2 + 7 files changed, 407 insertions(+), 26 deletions(-) create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Configuration.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/ConfigurationDescriptor.cs diff --git a/InversionOfControl/Castle.MicroKernel.Tests/Registration/ComponentRegistrationTestCase.cs b/InversionOfControl/Castle.MicroKernel.Tests/Registration/ComponentRegistrationTestCase.cs index 7617fbfa0..dce2f5884 100644 --- a/InversionOfControl/Castle.MicroKernel.Tests/Registration/ComponentRegistrationTestCase.cs +++ b/InversionOfControl/Castle.MicroKernel.Tests/Registration/ComponentRegistrationTestCase.cs @@ -15,11 +15,12 @@ namespace Castle.MicroKernel.Tests.Registration { using System.Collections; + using Castle.Core; using Castle.Core.Configuration; using Castle.MicroKernel.Registration; using Castle.MicroKernel.Tests.Lifestyle.Components; - using ClassComponents; - using Core; + using Castle.MicroKernel.Tests.Configuration.Components; + using Castle.MicroKernel.Tests.ClassComponents; using NUnit.Framework; [TestFixture] @@ -535,5 +536,29 @@ namespace Castle.MicroKernel.Tests.Registration Assert.AreSame(common1, component.Services[0]); Assert.AreSame(common2, component.Services[1]); } + + [Test] + public void AddComponent_WithComplexConfiguration_WorksFine() + { + kernel.Register( + Component.For() + .Configuration( + Child.ForName("parameters").Eq( + Child.ForName("complexparam").Eq( + Child.ForName("complexparametertype").Eq( + Child.ForName("mandatoryvalue").Eq("value1"), + Child.ForName("optionalvalue").Eq("value2") + ) + ) + ) + ) + ); + + ClassWithComplexParameter component = kernel.Resolve(); + Assert.IsNotNull(component); + Assert.IsNotNull(component.ComplexParam); + Assert.AreEqual("value1", component.ComplexParam.MandatoryValue); + Assert.AreEqual("value2", component.ComplexParam.OptionalValue); + } } } \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Castle.MicroKernel-vs2008.csproj b/InversionOfControl/Castle.MicroKernel/Castle.MicroKernel-vs2008.csproj index bc51ce68a..98006a823 100644 --- a/InversionOfControl/Castle.MicroKernel/Castle.MicroKernel-vs2008.csproj +++ b/InversionOfControl/Castle.MicroKernel/Castle.MicroKernel-vs2008.csproj @@ -321,6 +321,8 @@ + + diff --git a/InversionOfControl/Castle.MicroKernel/Registration/ComponentRegistration.cs b/InversionOfControl/Castle.MicroKernel/Registration/ComponentRegistration.cs index 055cc42c9..8c17aea45 100644 --- a/InversionOfControl/Castle.MicroKernel/Registration/ComponentRegistration.cs +++ b/InversionOfControl/Castle.MicroKernel/Registration/ComponentRegistration.cs @@ -33,6 +33,7 @@ namespace Castle.MicroKernel.Registration private Type implementation; private readonly List> descriptors; private ComponentModel componentModel; + private bool registered; /// /// Initializes a new instance of the class. @@ -40,10 +41,33 @@ namespace Castle.MicroKernel.Registration public ComponentRegistration() { overwrite = false; + registered = false; serviceType = typeof(S); descriptors = new List>(); } + /// + /// Initializes a new instance of the class + /// with an existing . + /// + public ComponentRegistration(ComponentModel componentModel) : this() + { + if (componentModel == null) + { + throw new ArgumentNullException("componentModel"); + } + + if (componentModel.Service != typeof(S)) + { + throw new ArgumentException("The componentModel Service does not" + + " match the expected type " + typeof(S).FullName); + } + + this.componentModel = componentModel; + name = componentModel.Name; + implementation = componentModel.Implementation; + } + public String Name { get { return name; } @@ -240,6 +264,16 @@ namespace Castle.MicroKernel.Registration } /// + /// With the configuration. + /// + /// The config nodes. + /// + public ComponentRegistration Configuration(params Node[] configNodes) + { + return AddDescriptor( new ConfigurationDescriptor(configNodes)); + } + + /// /// With the interceptors. /// /// The interceptors. @@ -266,34 +300,33 @@ namespace Castle.MicroKernel.Registration /// The kernel. void IRegistration.Register(IKernel kernel) { - if (componentModel == null) + if (!registered) { + registered = true; InitializeDefaults(); - componentModel = BuildComponentModel(kernel); - kernel.AddCustomComponent(componentModel); - } - } - /// - /// Builds the component model. - /// - /// - private ComponentModel BuildComponentModel(IKernel kernel) - { - IConfiguration configuration = EnsureComponentConfiguration(kernel); - foreach(ComponentDescriptor descriptor in descriptors) - { - descriptor.ApplyToConfiguration(kernel, configuration); + IConfiguration configuration = EnsureComponentConfiguration(kernel); + foreach(ComponentDescriptor descriptor in descriptors) + { + descriptor.ApplyToConfiguration(kernel, configuration); + } + + if (componentModel == null) + { + componentModel = kernel.ComponentModelBuilder.BuildModel( + name, serviceType, implementation, null); + } + + foreach (ComponentDescriptor descriptor in descriptors) + { + descriptor.ApplyToModel(kernel, componentModel); + } + + if (!kernel.HasComponent(name)) + { + kernel.AddCustomComponent(componentModel); + } } - - ComponentModel model = kernel.ComponentModelBuilder.BuildModel( - name, serviceType, implementation, null); - foreach(ComponentDescriptor descriptor in descriptors) - { - descriptor.ApplyToModel(kernel, model); - } - - return model; } /// @@ -374,6 +407,8 @@ namespace Castle.MicroKernel.Registration } } + #region Nested Type: ComponentRegistration + public class ComponentRegistration : ComponentRegistration { public ComponentRegistration() @@ -398,4 +433,6 @@ namespace Castle.MicroKernel.Registration return this; } } + + #endregion } diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Configuration.cs b/InversionOfControl/Castle.MicroKernel/Registration/Configuration.cs new file mode 100644 index 000000000..0092e5309 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Configuration.cs @@ -0,0 +1,275 @@ +// Copyright 2004-2008 Castle Project - http://www.castleproject.org/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Castle.MicroKernel.Registration +{ + using System; + using Castle.Core.Configuration; + + #region Node + + /// + /// Represents a configuration child. + /// + public abstract class Node + { + private readonly String name; + + protected Node(String name) + { + this.name = name; + } + + protected string Name + { + get { return name; } + } + + /// + /// Applies the configuration node. + /// + /// The configuration. + public abstract void ApplyTo(IConfiguration configuration); + } + + #endregion + + #region Attribute + + /// + /// Represents a configuration attribute. + /// + public class Attribute : Node + { + private readonly String value; + + internal Attribute(String name, String value) + : base(name) + { + this.value = value; + } + + /// + /// Applies the configuration node. + /// + /// The configuration. + public override void ApplyTo(IConfiguration configuration) + { + configuration.Attributes.Add(Name, value); + } + + /// + /// Create a with name. + /// + /// The attribute name. + /// The new + public static NamedAttribute ForName(String name) + { + return new NamedAttribute(name); + } + } + + #endregion + + #region NamedChild + + /// + /// Represents a named attribute. + /// + public class NamedAttribute + { + private readonly String name; + + internal NamedAttribute(String name) + { + this.name = name; + } + + /// + /// Builds the with name/value. + /// + /// The attribute value. + /// The new + public Attribute Eq(String value) + { + return new Attribute(name, value); + } + } + + #endregion + + #region Child + + /// + /// Represents a configuration child. + /// + public abstract class Child + { + /// + /// Create a with name. + /// + /// The child name. + /// The new + public static NamedChild ForName(String name) + { + return new NamedChild(name); + } + } + + #endregion + + #region NamedChild + + /// + /// Represents a named child. + /// + public class NamedChild : Node + { + internal NamedChild(String name) + : base(name) + { + } + + /// + /// Builds the with name/value. + /// + /// The child value. + /// The new + public SimpleChild Eq(String value) + { + return new SimpleChild(Name, value); + } + + /// + /// Builds the with name/config. + /// + /// The child configuration. + /// The new + public ComplexChild Eq(IConfiguration configNode) + { + return new ComplexChild(Name, configNode); + } + + /// + /// Builds the with name/config. + /// + /// The child nodes. + /// The new + public CompoundChild Eq(params Node[] childNodes) + { + return new CompoundChild(Name, childNodes); + } + + /// + /// Applies the configuration node. + /// + /// The configuration. + public override void ApplyTo(IConfiguration configuration) + { + MutableConfiguration node = new MutableConfiguration(Name); + configuration.Children.Add(node); + } + } + + #endregion + + #region SimpleChild + + /// + /// Represents a simple child node. + /// + public class SimpleChild : Node + { + private readonly String value; + + internal SimpleChild(String name, String value) + : base(name) + { + this.value = value; + } + + /// + /// Applies the configuration node. + /// + /// The configuration. + public override void ApplyTo(IConfiguration configuration) + { + MutableConfiguration node = new MutableConfiguration(Name, value); + configuration.Children.Add(node); + } + } + + #endregion + + #region ComplexChild + + /// + /// Represents a complex child node. + /// + public class ComplexChild : Node + { + private readonly IConfiguration configNode; + + internal ComplexChild(String name, IConfiguration configNode) + : base(name) + { + this.configNode = configNode; + } + + /// + /// Applies the configuration node. + /// + /// The configuration. + public override void ApplyTo(IConfiguration configuration) + { + MutableConfiguration node = new MutableConfiguration(Name); + node.Children.Add(configNode); + configuration.Children.Add(node); + } + } + + #endregion + + #region CompoundChild + + /// + /// Represents a compound child node. + /// + public class CompoundChild : Node + { + private readonly Node[] childNodes; + + internal CompoundChild(String name, Node[] childNodes) + : base(name) + { + this.childNodes = childNodes; + } + + /// + /// Applies the configuration node. + /// + /// The configuration. + public override void ApplyTo(IConfiguration configuration) + { + MutableConfiguration node = new MutableConfiguration(Name); + foreach (Node childNode in childNodes) + { + childNode.ApplyTo( node ); + } + configuration.Children.Add(node); + } + } + + #endregion +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/ConfigurationDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/ConfigurationDescriptor.cs new file mode 100644 index 000000000..03df7f5cb --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/ConfigurationDescriptor.cs @@ -0,0 +1,36 @@ +// Copyright 2004-2008 Castle Project - http://www.castleproject.org/ +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Castle.MicroKernel.Registration +{ + using Castle.Core.Configuration; + + public class ConfigurationDescriptor : ComponentDescriptor + { + private readonly Node[] configNodes; + + public ConfigurationDescriptor(params Node[] configNodes) + { + this.configNodes = configNodes; + } + + protected internal override void ApplyToConfiguration(IKernel kernel, IConfiguration configuration) + { + foreach (Node configNode in configNodes) + { + configNode.ApplyTo(configuration); + } + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Parameter.cs b/InversionOfControl/Castle.MicroKernel/Registration/Parameter.cs index 3c40e88a0..74060a416 100644 --- a/InversionOfControl/Castle.MicroKernel/Registration/Parameter.cs +++ b/InversionOfControl/Castle.MicroKernel/Registration/Parameter.cs @@ -73,6 +73,8 @@ namespace Castle.MicroKernel.Registration } } + #region ParameterKey + /// /// Represents a parameter key. /// @@ -112,5 +114,7 @@ namespace Castle.MicroKernel.Registration { return new Parameter(name, configNode); } + + #endregion } } \ No newline at end of file diff --git a/InversionOfControl/Changes.txt b/InversionOfControl/Changes.txt index 8c0f57d6b..711c73ffb 100644 --- a/InversionOfControl/Changes.txt +++ b/InversionOfControl/Changes.txt @@ -1,6 +1,8 @@ RC 4 ==== +- Added generalized configuration support to ComponentRegistration. + - Added IWindsorInstaller interface to enhance Windsor component installation. - Added AllTypesOf registration stratgey to simplify custom registration -- 2.11.4.GIT