From f10cfbf462ad964263fdc8ef6d71e7548d121e99 Mon Sep 17 00:00:00 2001 From: cneuwirt Date: Thu, 13 Dec 2007 10:47:08 +0000 Subject: [PATCH] Initial version of MicroKernel/Windsor fluent interface for registration (IoC-99) git-svn-id: https://svn.castleproject.org/svn/castle/trunk@4595 73e77b4c-caa6-f847-a29a-24ab75ae54b6 --- Core/Castle.Core/Castle.Core-vs2005.csproj | 1 + Core/Castle.Core/Model/ComponentModel.cs | 20 ++ .../Castle.MicroKernel.Tests-vs2005.csproj | 2 + .../Lifestyle/Components/MyCustomerActivator.cs | 44 +++ .../Registration/ComponentRegistrationTestCase.cs | 342 +++++++++++++++++++++ .../Castle.MicroKernel-vs2005.csproj | 23 ++ .../Castle.MicroKernel/DefaultKernel.cs | 12 + .../Castle.MicroKernel/Handlers/AbstractHandler.cs | 12 +- InversionOfControl/Castle.MicroKernel/IKernel.cs | 9 + .../Registration/AbstractPropertyDescriptor.cs | 57 ++++ .../Registration/AttributeDescriptor.cs | 39 +++ .../Registration/ComponentDescriptor.cs | 38 +++ .../Registration/ComponentInstanceDescriptor.cs | 35 +++ .../Registration/ComponentRegistration.cs | 303 ++++++++++++++++++ .../Registration/CustomDependencyDescriptor.cs | 39 +++ .../Registration/ExtendedPropertiesDescriptor.cs | 39 +++ .../Interceptor/InterceptorDescriptor.cs | 92 ++++++ .../Registration/Interceptor/InterceptorGroup.cs | 65 ++++ .../Registration/Lifestyle/Custom.cs | 32 ++ .../Registration/Lifestyle/LifestyleDescriptor.cs | 42 +++ .../Registration/Lifestyle/LifestyleGroup.cs | 60 ++++ .../Registration/Lifestyle/PerThread.cs | 26 ++ .../Registration/Lifestyle/PerWebRequest.cs | 26 ++ .../Registration/Lifestyle/Pooled.cs | 50 +++ .../Registration/Lifestyle/Singleton.cs | 26 ++ .../Registration/Lifestyle/Transient.cs | 26 ++ .../Castle.MicroKernel/Registration/Property.cs | 65 ++++ .../Registration/Proxy/ProxyGroup.cs | 48 +++ .../Registration/Proxy/ProxyInterfaces.cs | 39 +++ .../Registration/RegistrationGroup.cs | 41 +++ .../Registration/ServiceOverride.cs | 57 ++++ .../Registration/ServiceOverrideDescriptor.cs | 50 +++ .../Castle.Windsor/IWindsorContainer.cs | 8 + .../Castle.Windsor/WindsorContainer.cs | 11 + InversionOfControl/Changes.txt | 2 + 35 files changed, 1780 insertions(+), 1 deletion(-) create mode 100644 InversionOfControl/Castle.MicroKernel.Tests/Lifestyle/Components/MyCustomerActivator.cs create mode 100644 InversionOfControl/Castle.MicroKernel.Tests/Registration/ComponentRegistrationTestCase.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/AbstractPropertyDescriptor.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/AttributeDescriptor.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/ComponentDescriptor.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/ComponentInstanceDescriptor.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/ComponentRegistration.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/CustomDependencyDescriptor.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/ExtendedPropertiesDescriptor.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Interceptor/InterceptorDescriptor.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Interceptor/InterceptorGroup.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Custom.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/LifestyleDescriptor.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/LifestyleGroup.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/PerThread.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/PerWebRequest.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Pooled.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Singleton.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Transient.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Property.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Proxy/ProxyGroup.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/Proxy/ProxyInterfaces.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/RegistrationGroup.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/ServiceOverride.cs create mode 100644 InversionOfControl/Castle.MicroKernel/Registration/ServiceOverrideDescriptor.cs diff --git a/Core/Castle.Core/Castle.Core-vs2005.csproj b/Core/Castle.Core/Castle.Core-vs2005.csproj index c2fc64fbb..ffa4a97f1 100644 --- a/Core/Castle.Core/Castle.Core-vs2005.csproj +++ b/Core/Castle.Core/Castle.Core-vs2005.csproj @@ -93,6 +93,7 @@ + diff --git a/Core/Castle.Core/Model/ComponentModel.cs b/Core/Castle.Core/Model/ComponentModel.cs index ed981815d..0adc7921a 100644 --- a/Core/Castle.Core/Model/ComponentModel.cs +++ b/Core/Castle.Core/Model/ComponentModel.cs @@ -130,6 +130,9 @@ namespace Castle.Core /// Interceptors associated private InterceptorReferenceCollection interceptors; + /// /// Custom dependencies/// + [NonSerialized] private IDictionary customDependencies; + private bool requiresGenericArguments; #endregion @@ -352,5 +355,22 @@ namespace Castle.Core return dependencies; } } + + /// + /// Gets or sets the custom dependencies. + /// + /// The custom dependencies. + public IDictionary CustomDependencies + { + get + { + lock (this) + { + if (customDependencies == null) customDependencies = new HybridDictionary(); + } + return customDependencies; + } + set { customDependencies = value; } + } } } \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel.Tests/Castle.MicroKernel.Tests-vs2005.csproj b/InversionOfControl/Castle.MicroKernel.Tests/Castle.MicroKernel.Tests-vs2005.csproj index c27534101..df293214b 100644 --- a/InversionOfControl/Castle.MicroKernel.Tests/Castle.MicroKernel.Tests-vs2005.csproj +++ b/InversionOfControl/Castle.MicroKernel.Tests/Castle.MicroKernel.Tests-vs2005.csproj @@ -203,6 +203,7 @@ Code + Code @@ -247,6 +248,7 @@ Code + diff --git a/InversionOfControl/Castle.MicroKernel.Tests/Lifestyle/Components/MyCustomerActivator.cs b/InversionOfControl/Castle.MicroKernel.Tests/Lifestyle/Components/MyCustomerActivator.cs new file mode 100644 index 000000000..feeabe00c --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel.Tests/Lifestyle/Components/MyCustomerActivator.cs @@ -0,0 +1,44 @@ +// Copyright 2004-2007 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.Tests.Lifestyle.Components +{ + using Castle.Core; + using Castle.MicroKernel.ComponentActivator; + using Castle.MicroKernel.Tests.ClassComponents; + + /// + /// Summary description for MyCustomerActivator. + /// + public class MyCustomerActivator : AbstractComponentActivator + { + public MyCustomerActivator(ComponentModel model, IKernel kernel, + ComponentInstanceDelegate onCreation, + ComponentInstanceDelegate onDestruction) + : base(model, kernel, onCreation, onDestruction) + { + } + + protected override object InternalCreate(CreationContext context) + { + CustomerImpl customer = new CustomerImpl(); + customer.Name = "James Bond"; + return customer; + } + + protected override void InternalDestroy(object instance) + { + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel.Tests/Registration/ComponentRegistrationTestCase.cs b/InversionOfControl/Castle.MicroKernel.Tests/Registration/ComponentRegistrationTestCase.cs new file mode 100644 index 000000000..84288cdbb --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel.Tests/Registration/ComponentRegistrationTestCase.cs @@ -0,0 +1,342 @@ +// Copyright 2004-2007 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.Tests.Registration +{ + using System.Collections; + using Castle.Core; + using Castle.MicroKernel.Registration; + using Castle.MicroKernel.Tests.ClassComponents; + using Castle.MicroKernel.Tests.Lifestyle.Components; + using NUnit.Framework; + + [TestFixture] + public class ComponentRegistrationTestCase + { + private IKernel _kernel; + + [SetUp] + public void Init() + { + _kernel = new DefaultKernel(); + } + + [Test] + public void AddComponent_WithServiceOnly_RegisteredWithServiceTypeName() + { + _kernel.AddComponentEx() + .Register(); + + IHandler handler = _kernel.GetHandler(typeof(CustomerImpl)); + Assert.AreEqual(typeof(CustomerImpl), handler.ComponentModel.Service); + Assert.AreEqual(typeof(CustomerImpl), handler.ComponentModel.Implementation); + + CustomerImpl customer = _kernel.Resolve(); + Assert.IsNotNull(customer); + + object customer1 = _kernel[typeof(CustomerImpl).FullName]; + Assert.IsNotNull(customer1); + Assert.AreSame(customer, customer1); + } + + [Test] + public void AddComponent_WithServiceAndName_RegisteredWithName() + { + _kernel.AddComponentEx() + .WithName("customer") + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual("customer", handler.ComponentModel.Name); + Assert.AreEqual(typeof(CustomerImpl), handler.ComponentModel.Service); + Assert.AreEqual(typeof(CustomerImpl), handler.ComponentModel.Implementation); + + CustomerImpl customer = (CustomerImpl)_kernel["customer"]; + Assert.IsNotNull(customer); + } + + [Test] + [ExpectedException(typeof(ComponentRegistrationException), + "This component has already been assigned name 'customer'")] + public void AddComponent_WithNameAlreadyAssigned_ThrowsException() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithName("customer1") + .Register(); + } + + [Test] + public void AddComponent_WithServiceAndClass_RegisteredWithClassTypeName() + { + _kernel.AddComponentEx() + .WithImplementation() + .Register(); + + ICustomer customer = _kernel.Resolve(); + Assert.IsNotNull(customer); + + object customer1 = _kernel[typeof(CustomerImpl).FullName]; + Assert.IsNotNull(customer1); + } + + [Test] + [ExpectedException(typeof(ComponentRegistrationException), + "This component has already been assigned implementation Castle.MicroKernel.Tests.ClassComponents.CustomerImpl")] + public void AddComponent_WithImplementationAlreadyAssigned_ThrowsException() + { + _kernel.AddComponentEx() + .WithImplementation() + .WithImplementation() + .Register(); + } + + [Test] + public void AddComponent_WithInstance_UsesInstance() + { + CustomerImpl customer = new CustomerImpl(); + + _kernel.AddComponentEx() + .WithName("key") + .WithInstance(customer) + .Register(); + Assert.IsTrue(_kernel.HasComponent("key")); + + CustomerImpl customer2 = _kernel["key"] as CustomerImpl; + Assert.AreSame(customer, customer2); + + customer2 = _kernel[typeof(ICustomer)] as CustomerImpl; + Assert.AreSame(customer, customer2); + } + + [Test] + public void AddComponent_WithTransientLifestyle_WorksFine() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithImplementation() + .WithLifestyle.Transient + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual(LifestyleType.Transient, handler.ComponentModel.LifestyleType); + } + + [Test] + public void AddComponent_WithSingletonLifestyle_WorksFine() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithImplementation() + .WithLifestyle.Singleton + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual(LifestyleType.Singleton, handler.ComponentModel.LifestyleType); + } + + [Test] + public void AddComponent_WithCustomLifestyle_WorksFine() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithImplementation() + .WithLifestyle.Custom() + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual(LifestyleType.Custom, handler.ComponentModel.LifestyleType); + } + + [Test] + public void AddComponent_WithThreadLifestyle_WorksFine() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithImplementation() + .WithLifestyle.PerThread + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual(LifestyleType.Thread, handler.ComponentModel.LifestyleType); + } + + [Test] + public void AddComponent_WithPerWebRequestLifestyle_WorksFine() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithImplementation() + .WithLifestyle.PerWebRequest + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual(LifestyleType.PerWebRequest, handler.ComponentModel.LifestyleType); + } + + [Test] + public void AddComponent_WithPooledLifestyle_WorksFine() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithImplementation() + .WithLifestyle.Pooled + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual(LifestyleType.Pooled, handler.ComponentModel.LifestyleType); + } + + [Test] + public void AddComponent_WithPooledWithSizeLifestyle_WorksFine() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithImplementation() + .WithLifestyle.PooledWithSize(5, 10) + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual(LifestyleType.Pooled, handler.ComponentModel.LifestyleType); + } + + [Test] + public void AddComponent_WithActivator_WorksFine() + { + _kernel.AddComponentEx() + .WithName("customer") + .WithImplementation() + .WithActivator() + .Register(); + + IHandler handler = _kernel.GetHandler("customer"); + Assert.AreEqual(typeof(MyCustomerActivator), handler.ComponentModel.CustomComponentActivator); + + ICustomer customer = _kernel.Resolve(); + Assert.AreEqual("James Bond", customer.Name); + } + + + [Test] + public void AddComponent_WithExtendedProperties_WorksFine() + { + _kernel.AddComponentEx() + .WithImplementation() + .WithExtendedProperties( + Property.WithKey("key1").Eq("value1"), + Property.WithKey("key2").Eq("value2")) + .Register(); + + IHandler handler = _kernel.GetHandler(typeof(ICustomer)); + Assert.AreEqual("value1", handler.ComponentModel.ExtendedProperties["key1"]); + Assert.AreEqual("value2", handler.ComponentModel.ExtendedProperties["key2"]); + } + + [Test] + public void AddComponent_WithCustomDependencies_WorksFine() + { + _kernel.AddComponentEx() + .WithImplementation() + .WithCustomDependencies( + Property.WithKey("Name").Eq("Caption Hook"), + Property.WithKey("Address").Eq("Fairyland"), + Property.WithKey("Age").Eq(45)) + .Register(); + + ICustomer customer = _kernel.Resolve(); + Assert.AreEqual(customer.Name, "Caption Hook"); + Assert.AreEqual(customer.Address, "Fairyland"); + Assert.AreEqual(customer.Age, 45); + } + + [Test] + public void AddComponent_WithCustomDependenciesDictionary_WorksFine() + { + Hashtable customDependencies = new Hashtable(); + customDependencies["Name"] = "Caption Hook"; + customDependencies["Address"] = "Fairyland"; + customDependencies["Age"] = 45; + + _kernel.AddComponentEx() + .WithImplementation() + .WithCustomDependencies(customDependencies) + .Register(); + + ICustomer customer = _kernel.Resolve(); + Assert.AreEqual(customer.Name, "Caption Hook"); + Assert.AreEqual(customer.Address, "Fairyland"); + Assert.AreEqual(customer.Age, 45); + } + + [Test] + public void AddComponent_WithServiceOverrides_WorksFine() + { + _kernel + .AddComponentEx() + .WithName("customer1") + .WithImplementation() + .WithCustomDependencies( + Property.WithKey("Name").Eq("Caption Hook"), + Property.WithKey("Address").Eq("Fairyland"), + Property.WithKey("Age").Eq(45)) + .Register() + .AddComponentEx() + .WithName("customer2") + .WithCustomDependencies( + Property.WithKey("Name").Eq("Bigfoot"), + Property.WithKey("Address").Eq("Forest"), + Property.WithKey("Age").Eq(100)) + .WithServiceOverrides( + ServiceOverride.WithKey("customer").Eq("customer1")) + .Register(); + + CustomerChain1 customer = (CustomerChain1)_kernel["customer2"]; + Assert.IsNotNull(customer.CustomerBase); + Assert.AreEqual(customer.CustomerBase.Name, "Caption Hook"); + Assert.AreEqual(customer.CustomerBase.Address, "Fairyland"); + Assert.AreEqual(customer.CustomerBase.Age, 45); + } + + [Test] + public void AddComponent_WithServiceOverridesDictionary_WorksFine() + { + Hashtable serviceOverrides = new Hashtable(); + serviceOverrides["customer"] = "customer1"; + + _kernel + .AddComponentEx() + .WithName("customer1") + .WithImplementation() + .WithCustomDependencies( + Property.WithKey("Name").Eq("Caption Hook"), + Property.WithKey("Address").Eq("Fairyland"), + Property.WithKey("Age").Eq(45)) + .Register() + .AddComponentEx() + .WithName("customer2") + .WithCustomDependencies( + Property.WithKey("Name").Eq("Bigfoot"), + Property.WithKey("Address").Eq("Forest"), + Property.WithKey("Age").Eq(100)) + .WithServiceOverrides(serviceOverrides) + .Register(); + + CustomerChain1 customer = (CustomerChain1)_kernel["customer2"]; + Assert.IsNotNull(customer.CustomerBase); + Assert.AreEqual(customer.CustomerBase.Name, "Caption Hook"); + Assert.AreEqual(customer.CustomerBase.Address, "Fairyland"); + Assert.AreEqual(customer.CustomerBase.Age, 45); + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Castle.MicroKernel-vs2005.csproj b/InversionOfControl/Castle.MicroKernel/Castle.MicroKernel-vs2005.csproj index 64e4b7941..1d1f6a5c8 100644 --- a/InversionOfControl/Castle.MicroKernel/Castle.MicroKernel-vs2005.csproj +++ b/InversionOfControl/Castle.MicroKernel/Castle.MicroKernel-vs2005.csproj @@ -310,6 +310,29 @@ + + + + + + + + + + + + + + + + + + + + + + + Code diff --git a/InversionOfControl/Castle.MicroKernel/DefaultKernel.cs b/InversionOfControl/Castle.MicroKernel/DefaultKernel.cs index 219da3167..4ebf8f2fe 100644 --- a/InversionOfControl/Castle.MicroKernel/DefaultKernel.cs +++ b/InversionOfControl/Castle.MicroKernel/DefaultKernel.cs @@ -25,6 +25,7 @@ namespace Castle.MicroKernel using Castle.MicroKernel.Handlers; using Castle.MicroKernel.ModelBuilder; using Castle.MicroKernel.Proxy; + using Castle.MicroKernel.Registration; using Castle.MicroKernel.Releasers; using Castle.MicroKernel.Resolvers; using Castle.MicroKernel.SubSystems.Configuration; @@ -546,6 +547,17 @@ namespace Castle.MicroKernel } /// + /// Adds a component to be registered with the + /// using a fluent interface. + /// + /// The service to manage. + /// The + public ComponentRegistration AddComponentEx() + { + return new ComponentRegistration(this, this); + } + + /// /// Returns the component instance by the service type /// using dynamic arguments /// diff --git a/InversionOfControl/Castle.MicroKernel/Handlers/AbstractHandler.cs b/InversionOfControl/Castle.MicroKernel/Handlers/AbstractHandler.cs index 58cae7363..1ced15476 100644 --- a/InversionOfControl/Castle.MicroKernel/Handlers/AbstractHandler.cs +++ b/InversionOfControl/Castle.MicroKernel/Handlers/AbstractHandler.cs @@ -61,7 +61,7 @@ namespace Castle.MicroKernel.Handlers { this.model = model; state = HandlerState.Valid; - customParameters = new HybridDictionary(true); + InitializeCustomDependencies(); } #region IHandler Members @@ -645,6 +645,16 @@ namespace Castle.MicroKernel.Handlers } } + private void InitializeCustomDependencies() + { + customParameters = new HybridDictionary(true); + + foreach (DictionaryEntry customParameter in model.CustomDependencies) + { + customParameters.Add(customParameter.Key, customParameter.Value); + } + } + private bool HasValidComponent(Type service, DependencyModel dependency) { foreach (IHandler handler in kernel.GetHandlers(service)) diff --git a/InversionOfControl/Castle.MicroKernel/IKernel.cs b/InversionOfControl/Castle.MicroKernel/IKernel.cs index e0acf2fa1..3bfd3d188 100644 --- a/InversionOfControl/Castle.MicroKernel/IKernel.cs +++ b/InversionOfControl/Castle.MicroKernel/IKernel.cs @@ -17,6 +17,7 @@ namespace Castle.MicroKernel using System; using System.Collections; using Castle.Core; + using Castle.MicroKernel.Registration; /// /// The IKernel interface exposes all the functionality @@ -298,6 +299,14 @@ namespace Castle.MicroKernel void AddComponentInstance(string key, Type serviceType, Type classType, object instance); /// + /// Adds a component to be registered with the + /// using a fluent interface. + /// + /// The service to manage. + /// The + ComponentRegistration AddComponentEx(); + + /// /// Returns true if the specified component was /// found and could be removed (i.e. no other component depends on it) /// diff --git a/InversionOfControl/Castle.MicroKernel/Registration/AbstractPropertyDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/AbstractPropertyDescriptor.cs new file mode 100644 index 000000000..c77f866a0 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/AbstractPropertyDescriptor.cs @@ -0,0 +1,57 @@ +// Copyright 2004-2007 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 System.Collections; + using Core; + + public abstract class AbstractPropertyDescriptior : ComponentDescriptor + { + private readonly Property[] properties; + private readonly IDictionary dictionary; + + protected AbstractPropertyDescriptior(params Property[] properties) + { + this.properties = properties; + } + + protected AbstractPropertyDescriptior(IDictionary dictionary) + { + this.dictionary = dictionary; + } + + protected internal override void ApplyToModel(ComponentModel model) + { + if (dictionary != null) + { + foreach(DictionaryEntry property in dictionary) + { + ApplyProperty(model, property.Key.ToString(), property.Value); + } + } + else if (properties != null) + { + foreach(Property property in properties) + { + ApplyProperty(model, property.Key, property.Value); + } + } + } + + protected abstract void ApplyProperty(ComponentModel model, + String key, Object value); + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/AttributeDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/AttributeDescriptor.cs new file mode 100644 index 000000000..d75cb857d --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/AttributeDescriptor.cs @@ -0,0 +1,39 @@ +// Copyright 2004-2007 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; + + public class AttributeDescriptor : ComponentDescriptor + { + private readonly String name; + private readonly String value; + + public AttributeDescriptor(String name, String value) + { + this.name = name; + this.value = value; + } + + protected internal override void ApplyToConfiguration(IConfiguration configuration) + { + if (configuration.Attributes[name] == null || Registration.Overwrite) + { + configuration.Attributes[name] = value; + } + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/ComponentDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/ComponentDescriptor.cs new file mode 100644 index 000000000..13c7208e5 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/ComponentDescriptor.cs @@ -0,0 +1,38 @@ +// Copyright 2004-2007 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; + using Castle.Core.Configuration; + + public abstract class ComponentDescriptor + { + private ComponentRegistration registration; + + internal ComponentRegistration Registration + { + get { return registration; } + set { registration = value; } + } + + protected internal virtual void ApplyToConfiguration(IConfiguration configuration) + { + } + + protected internal virtual void ApplyToModel(ComponentModel model) + { + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/ComponentInstanceDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/ComponentInstanceDescriptor.cs new file mode 100644 index 000000000..11c092ec0 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/ComponentInstanceDescriptor.cs @@ -0,0 +1,35 @@ +// Copyright 2004-2007 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; + using Castle.MicroKernel.ComponentActivator; + + public class ComponentInstanceDescriptior : ComponentDescriptor + { + private readonly object instance; + + public ComponentInstanceDescriptior(object instance) + { + this.instance = instance; + } + + protected internal override void ApplyToModel(ComponentModel model) + { + model.CustomComponentActivator = typeof(ExternalInstanceActivator); + model.ExtendedProperties["instance"] = instance; + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/ComponentRegistration.cs b/InversionOfControl/Castle.MicroKernel/Registration/ComponentRegistration.cs new file mode 100644 index 000000000..d880468b5 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/ComponentRegistration.cs @@ -0,0 +1,303 @@ +// Copyright 2004-2007 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 System.Collections; + using System.Collections.Generic; + using Castle.Core; + using Castle.Core.Configuration; + + /// + /// + /// + /// The service type + /// The chaining type + public class ComponentRegistration + { + private String name; + private bool overwrite; + private readonly IKernel kernel; + private Type classType; + private readonly T chain; + private readonly List> descriptors; + + /// + /// Initializes a new instance of the class. + /// + /// The kernel. + /// The chain + public ComponentRegistration(IKernel kernel, T chain) + { + overwrite = false; + this.kernel = kernel; + this.chain = chain; + descriptors = new List>(); + } + + internal bool Overwrite + { + get { return overwrite; } + } + + /// + /// With the overwrite. + /// + /// + public ComponentRegistration WithOverwrite() + { + overwrite = true; + return this; + } + + /// + /// With the name. + /// + /// The name. + /// + public ComponentRegistration WithName(String name) + { + if (this.name != null) + { + String message = String.Format("This component has " + + "already been assigned name '{0}'", this.name); + + throw new ComponentRegistrationException(message); + } + + this.name = name; + return this; + } + + public ComponentRegistration WithImplementation() + { + if (classType != null) + { + String message = String.Format("This component has " + + "already been assigned implementation {0}", classType.FullName); + + throw new ComponentRegistrationException(message); + } + + classType = typeof(C); + return this; + } + + /// + /// With the instance. + /// + /// The instance. + /// + public ComponentRegistration WithInstance(S instance) + { + return AddDescriptor(new ComponentInstanceDescriptior(instance)); + } + + /// + /// Gets the proxy. + /// + /// The proxy. + public Proxy.ProxyGroup Proxy + { + get { return new Proxy.ProxyGroup(this); } + } + + /// + /// Gets the with lifestyle. + /// + /// The with lifestyle. + public Lifestyle.LifestyleGroup WithLifestyle + { + get { return new Lifestyle.LifestyleGroup(this); } + } + + /// + /// With the activator. + /// + /// + public ComponentRegistration WithActivator() where A : IComponentActivator + { + return AddAttributeDescriptor("componentActivatorType", typeof(A).AssemblyQualifiedName); + } + + /// + /// With the extended properties. + /// + /// The properties. + /// + public ComponentRegistration WithExtendedProperties(params Property[] properties) + { + return AddDescriptor(new ExtendedPropertiesDescriptor(properties)); + } + + /// + /// With the custom dependencies. + /// + /// The dependencies. + /// + public ComponentRegistration WithCustomDependencies(params Property[] dependencies) + { + return AddDescriptor(new CustomDependencyDescriptor(dependencies)); + } + + /// + /// With the custom dependencies. + /// + /// The dependencies. + /// + public ComponentRegistration WithCustomDependencies(IDictionary dependencies) + { + return AddDescriptor(new CustomDependencyDescriptor(dependencies)); + } + + /// + /// With the service overrides. + /// + /// The overrides. + /// + public ComponentRegistration WithServiceOverrides(params ServiceOverride[] overrides) + { + return AddDescriptor(new ServiceOverrideDescriptor(overrides)); + } + + /// + /// With the service overrides. + /// + /// The overrides. + /// + public ComponentRegistration WithServiceOverrides(IDictionary overrides) + { + return AddDescriptor(new ServiceOverrideDescriptor(overrides)); + } + + /// + /// With the interceptors. + /// + /// The interceptors. + /// + public Interceptor.InterceptorGroup WithInterceptors( + params InterceptorReference[] interceptors) + { + return new Interceptor.InterceptorGroup(this, interceptors); + } + + /// + /// Ases the startable. + /// + /// + public ComponentRegistration AsStartable() + { + return AddDescriptor(new ExtendedPropertiesDescriptor( + Property.WithKey("startable").Eq(true))); + } + + /// + /// Registers this instance. + /// + /// + public T Register() + { + InitializeDefaults(); + ComponentModel model = BuildComponentModel(); + kernel.AddCustomComponent(model); + return chain; + } + + /// + /// Builds the component model. + /// + /// + private ComponentModel BuildComponentModel() + { + IConfiguration configuration = EnsureComponentConfiguration(); + foreach(ComponentDescriptor descriptor in descriptors) + { + descriptor.ApplyToConfiguration(configuration); + } + + ComponentModel model = kernel.ComponentModelBuilder.BuildModel( + name, typeof(S), classType, null); + foreach(ComponentDescriptor descriptor in descriptors) + { + descriptor.ApplyToModel(model); + } + + return model; + } + + /// + /// Adds the attribute descriptor. + /// + /// The name. + /// The value. + /// + public ComponentRegistration AddAttributeDescriptor(string name, string value) + { + AddDescriptor(new AttributeDescriptor(name, value)); + return this; + } + + /// + /// Adds the descriptor. + /// + /// The descriptor. + /// + public ComponentRegistration AddDescriptor(ComponentDescriptor descriptor) + { + descriptor.Registration = this; + descriptors.Add(descriptor); + return this; + } + + internal void AddParameter(ComponentModel model, String name, String value) + { + IConfiguration configuration = EnsureComponentConfiguration(); + IConfiguration parameters = configuration.Children["parameters"]; + if (parameters == null) + { + parameters = new MutableConfiguration("component"); + configuration.Children.Add(parameters); + } + + MutableConfiguration reference = new MutableConfiguration(name, value); + parameters.Children.Add(reference); + model.Parameters.Add(name, value); + } + + private void InitializeDefaults() + { + if (classType == null) + { + classType = typeof(S); + } + + if (String.IsNullOrEmpty(name)) + { + name = classType.FullName; + } + } + + private IConfiguration EnsureComponentConfiguration() + { + IConfiguration configuration = kernel.ConfigurationStore.GetComponentConfiguration(name); + if (configuration == null) + { + configuration = new MutableConfiguration("component"); + kernel.ConfigurationStore.AddComponentConfiguration(name, configuration); + } + return configuration; + } + } +} diff --git a/InversionOfControl/Castle.MicroKernel/Registration/CustomDependencyDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/CustomDependencyDescriptor.cs new file mode 100644 index 000000000..5df54690b --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/CustomDependencyDescriptor.cs @@ -0,0 +1,39 @@ +// Copyright 2004-2007 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 System.Collections; + using Castle.Core; + + public class CustomDependencyDescriptor : AbstractPropertyDescriptior + { + public CustomDependencyDescriptor(params Property[] properties) + : base(properties) + { + } + + public CustomDependencyDescriptor(IDictionary dictionary) + : base(dictionary) + { + } + + protected override void ApplyProperty(ComponentModel model, + String key, Object value) + { + model.CustomDependencies[key] = value; + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/ExtendedPropertiesDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/ExtendedPropertiesDescriptor.cs new file mode 100644 index 000000000..012f7bb1b --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/ExtendedPropertiesDescriptor.cs @@ -0,0 +1,39 @@ +// Copyright 2004-2007 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 System.Collections; + using Castle.Core; + + public class ExtendedPropertiesDescriptor : AbstractPropertyDescriptior + { + public ExtendedPropertiesDescriptor(params Property[] properties) + : base(properties) + { + } + + public ExtendedPropertiesDescriptor(IDictionary dictionary) + : base(dictionary) + { + } + + protected override void ApplyProperty(ComponentModel model, + String key, Object value) + { + model.ExtendedProperties[key] = value; + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Interceptor/InterceptorDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/Interceptor/InterceptorDescriptor.cs new file mode 100644 index 000000000..52904b881 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Interceptor/InterceptorDescriptor.cs @@ -0,0 +1,92 @@ +// Copyright 2004-2007 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.Interceptor +{ + using System; + using Castle.Core; + + public class InterceptorDescriptor : ComponentDescriptor + { + private readonly Where where; + private readonly int insertIndex; + private readonly InterceptorReference[] interceptors; + + public enum Where + { + First, + Last, + Insert, + Default + } + + public InterceptorDescriptor(InterceptorReference[] interceptors, Where where) + { + this.interceptors = interceptors; + this.where = where; + } + + public InterceptorDescriptor(InterceptorReference[] interceptors, int insertIndex) + : this(interceptors, Where.Insert) + { + if (insertIndex < 0) + { + throw new ArgumentOutOfRangeException("insertIndex", "insertIndex must be >= 0"); + } + + this.insertIndex = insertIndex; + } + + public InterceptorDescriptor(InterceptorReference[] interceptors) + { + where = Where.Default; + this.interceptors = interceptors; + } + + protected internal override void ApplyToModel(ComponentModel model) + { + foreach(InterceptorReference interceptor in interceptors) + { + switch (where) + { + case Where.First: + model.Interceptors.AddFirst(interceptor); + break; + + case Where.Last: + model.Interceptors.AddLast(interceptor); + break; + + case Where.Insert: + model.Interceptors.Insert(insertIndex, interceptor); + break; + + default: + model.Interceptors.Add(interceptor); + break; + } + + AddDependencyModel(interceptor, model); + } + } + + private static void AddDependencyModel(InterceptorReference interceptor, ComponentModel model) + { + DependencyModel dependency = new DependencyModel( + DependencyType.Service, interceptor.ComponentKey, + interceptor.ServiceType, false); + model.Dependencies.Add(dependency); + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Interceptor/InterceptorGroup.cs b/InversionOfControl/Castle.MicroKernel/Registration/Interceptor/InterceptorGroup.cs new file mode 100644 index 000000000..c5a90714d --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Interceptor/InterceptorGroup.cs @@ -0,0 +1,65 @@ +// Copyright 2004-2007 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.Interceptor +{ + using Core; + + public class InterceptorGroup : RegistrationGroup + { + private readonly InterceptorReference[] interceptors; + + public InterceptorGroup(ComponentRegistration registration, + InterceptorReference[] interceptors) + : base(registration) + { + this.interceptors = interceptors; + } + + public ComponentRegistration Anywhere + { + get + { + AddDescriptor(new InterceptorDescriptor(interceptors)); + return Registration; + } + } + + public ComponentRegistration First + { + get + { + AddDescriptor(new InterceptorDescriptor( + interceptors, InterceptorDescriptor.Where.First)); + return Registration; + } + } + + public ComponentRegistration Last + { + get + { + AddDescriptor(new InterceptorDescriptor( + interceptors, InterceptorDescriptor.Where.Last)); + return Registration; + } + } + + public ComponentRegistration AtIndex(int index) + { + AddDescriptor(new InterceptorDescriptor(interceptors, index)); + return Registration; + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Custom.cs b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Custom.cs new file mode 100644 index 000000000..c3b215c6c --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Custom.cs @@ -0,0 +1,32 @@ +// Copyright 2004-2007 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.Lifestyle +{ + using Castle.Core; + using Castle.Core.Configuration; + + public class Custom : LifestyleDescriptor where L : ILifestyleManager + { + public Custom() + : base(LifestyleType.Custom) + { + } + + protected override void ApplyLifestyleDetails(IConfiguration configuration) + { + configuration.Attributes["customLifestyleType"] = typeof(L).AssemblyQualifiedName; + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/LifestyleDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/LifestyleDescriptor.cs new file mode 100644 index 000000000..de0c39e7b --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/LifestyleDescriptor.cs @@ -0,0 +1,42 @@ +// Copyright 2004-2007 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; + using Castle.Core.Configuration; + + public abstract class LifestyleDescriptor : ComponentDescriptor + { + private readonly LifestyleType lifestyle; + + protected LifestyleDescriptor(LifestyleType lifestyle) + { + this.lifestyle = lifestyle; + } + + protected internal override void ApplyToConfiguration(IConfiguration configuration) + { + if (configuration.Attributes["lifestyle"] == null || Registration.Overwrite) + { + configuration.Attributes["lifestyle"] = lifestyle.ToString(); + ApplyLifestyleDetails(configuration); + } + } + + protected virtual void ApplyLifestyleDetails(IConfiguration configuration) + { + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/LifestyleGroup.cs b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/LifestyleGroup.cs new file mode 100644 index 000000000..969ded41e --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/LifestyleGroup.cs @@ -0,0 +1,60 @@ +// Copyright 2004-2007 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.Lifestyle +{ + public class LifestyleGroup : RegistrationGroup + { + public LifestyleGroup(ComponentRegistration registration) + : base(registration) + { + } + + public ComponentRegistration Transient + { + get { return AddDescriptor(new Transient()); } + } + + public ComponentRegistration Singleton + { + get { return AddDescriptor(new Singleton()); } + } + + public ComponentRegistration PerThread + { + get { return AddDescriptor(new PerThread()); } + } + + public ComponentRegistration PerWebRequest + { + get { return AddDescriptor(new PerWebRequest()); } + } + + public ComponentRegistration Pooled + { + get { return AddDescriptor(new Pooled()); } + } + + public ComponentRegistration PooledWithSize(int initialSize, int maxSize) + { + return AddDescriptor(new Pooled(initialSize, maxSize)); + } + + public ComponentRegistration Custom() + where L : ILifestyleManager, new() + { + return AddDescriptor(new Custom()); + } + } +} diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/PerThread.cs b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/PerThread.cs new file mode 100644 index 000000000..41fc6d0a2 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/PerThread.cs @@ -0,0 +1,26 @@ +// Copyright 2004-2007 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.Lifestyle +{ + using Castle.Core; + + public class PerThread : LifestyleDescriptor + { + public PerThread() + : base(LifestyleType.Thread) + { + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/PerWebRequest.cs b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/PerWebRequest.cs new file mode 100644 index 000000000..8d4195379 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/PerWebRequest.cs @@ -0,0 +1,26 @@ +// Copyright 2004-2007 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.Lifestyle +{ + using Castle.Core; + + public class PerWebRequest : LifestyleDescriptor + { + public PerWebRequest() + : base(LifestyleType.PerWebRequest) + { + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Pooled.cs b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Pooled.cs new file mode 100644 index 000000000..f0d4ca6ec --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Pooled.cs @@ -0,0 +1,50 @@ +// Copyright 2004-2007 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.Lifestyle +{ + using Castle.Core; + using Castle.Core.Configuration; + + public class Pooled : LifestyleDescriptor + { + private readonly int? initialSize; + private readonly int? maxSize; + + public Pooled() + : base(LifestyleType.Pooled) + { + } + + public Pooled(int initialSize, int maxSize) + : this() + { + this.initialSize = initialSize; + this.maxSize = maxSize; + } + + protected override void ApplyLifestyleDetails(IConfiguration configuration) + { + if (initialSize.HasValue) + { + configuration.Attributes["initialPoolSize"] = initialSize.ToString(); + } + + if (maxSize.HasValue) + { + configuration.Attributes["maxPoolSize"] = maxSize.ToString(); + } + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Singleton.cs b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Singleton.cs new file mode 100644 index 000000000..7a9837c9f --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Singleton.cs @@ -0,0 +1,26 @@ +// Copyright 2004-2007 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.Lifestyle +{ + using Castle.Core; + + public class Singleton : LifestyleDescriptor + { + public Singleton() + : base(LifestyleType.Singleton) + { + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Transient.cs b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Transient.cs new file mode 100644 index 000000000..5566b4563 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Lifestyle/Transient.cs @@ -0,0 +1,26 @@ +// Copyright 2004-2007 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.Lifestyle +{ + using Castle.Core; + + public class Transient : LifestyleDescriptor + { + public Transient() + : base(LifestyleType.Transient) + { + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Property.cs b/InversionOfControl/Castle.MicroKernel/Registration/Property.cs new file mode 100644 index 000000000..7ec385d5e --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Property.cs @@ -0,0 +1,65 @@ +// Copyright 2004-2007 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; + + public class Property + { + private readonly String key; + private readonly object value; + + internal Property(String key, Object value) + { + this.key = key; + this.value = value; + } + + public string Key + { + get { return key; } + } + + public object Value + { + get { return value; } + } + + public static PropertyKey WithKey(String key) + { + return new PropertyKey(key); + } + } + + public class PropertyKey + { + private readonly String name; + + internal PropertyKey(String name) + { + this.name = name; + } + + public string Name + { + get { return name; } + } + + public Property Eq(Object value) + { + return new Property(name, value); + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Proxy/ProxyGroup.cs b/InversionOfControl/Castle.MicroKernel/Registration/Proxy/ProxyGroup.cs new file mode 100644 index 000000000..0f16b844c --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Proxy/ProxyGroup.cs @@ -0,0 +1,48 @@ +// Copyright 2004-2007 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.Proxy +{ + using System; + + public class ProxyGroup : RegistrationGroup + { + public ProxyGroup(ComponentRegistration registration) + : base(registration) + { + } + + public ComponentRegistration UsingSingleInterface + { + get + { + return AddAttributeDescriptor("useSingleInterfaceProxy", "true"); + } + } + + public ComponentRegistration AsMarshalByRefClass + { + get + { + return AddAttributeDescriptor("marshalByRefProxy", "true"); + } + } + + public ComponentRegistration AdditionalInterfaces(params Type[] interfaces) + { + AddDescriptor(new ProxyInterfaces(interfaces)); + return Registration; + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/Proxy/ProxyInterfaces.cs b/InversionOfControl/Castle.MicroKernel/Registration/Proxy/ProxyInterfaces.cs new file mode 100644 index 000000000..48874a7cd --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/Proxy/ProxyInterfaces.cs @@ -0,0 +1,39 @@ +// Copyright 2004-2007 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.Proxy +{ + using System; + using Castle.Core; + using Castle.MicroKernel.Proxy; + + public class ProxyInterfaces : ComponentDescriptor + { + private readonly Type[] interfaces; + + public ProxyInterfaces(Type[] interfaces) + { + this.interfaces = interfaces; + } + + protected internal override void ApplyToModel(ComponentModel model) + { + if (interfaces.Length > 0) + { + ProxyOptions options = ProxyUtil.ObtainProxyOptions(model, true); + options.AddAdditionalInterfaces(interfaces); + } + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/RegistrationGroup.cs b/InversionOfControl/Castle.MicroKernel/Registration/RegistrationGroup.cs new file mode 100644 index 000000000..4a9e52f2a --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/RegistrationGroup.cs @@ -0,0 +1,41 @@ +// Copyright 2004-2007 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 +{ + public abstract class RegistrationGroup + { + private readonly ComponentRegistration registration; + + public RegistrationGroup(ComponentRegistration registration) + { + this.registration = registration; + } + + public ComponentRegistration Registration + { + get { return registration; } + } + + protected ComponentRegistration AddAttributeDescriptor(string name, string value) + { + return registration.AddDescriptor(new AttributeDescriptor(name, value)); + } + + protected ComponentRegistration AddDescriptor(ComponentDescriptor descriptor) + { + return registration.AddDescriptor(descriptor); + } + } +} diff --git a/InversionOfControl/Castle.MicroKernel/Registration/ServiceOverride.cs b/InversionOfControl/Castle.MicroKernel/Registration/ServiceOverride.cs new file mode 100644 index 000000000..dd315056e --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/ServiceOverride.cs @@ -0,0 +1,57 @@ +// Copyright 2004-2007 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; + + public class ServiceOverride : Property + { + internal ServiceOverride(String key, String value) + : base(key, value) + { + } + + public new String Value + { + get { return (String) base.Value; } + } + + + public new static ServiceOverrideKey WithKey(String key) + { + return new ServiceOverrideKey(key); + } + } + + public class ServiceOverrideKey + { + private readonly String name; + + internal ServiceOverrideKey(String name) + { + this.name = name; + } + + public string Name + { + get { return name; } + } + + public ServiceOverride Eq(String value) + { + return new ServiceOverride(name, value); + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.MicroKernel/Registration/ServiceOverrideDescriptor.cs b/InversionOfControl/Castle.MicroKernel/Registration/ServiceOverrideDescriptor.cs new file mode 100644 index 000000000..a93df1834 --- /dev/null +++ b/InversionOfControl/Castle.MicroKernel/Registration/ServiceOverrideDescriptor.cs @@ -0,0 +1,50 @@ +// Copyright 2004-2007 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 System.Collections; + using Castle.Core; + using Castle.MicroKernel.Util; + + public class ServiceOverrideDescriptor : AbstractPropertyDescriptior + { + public ServiceOverrideDescriptor(params ServiceOverride[] overrides) + : base(overrides) + { + } + + public ServiceOverrideDescriptor(IDictionary dictionary) + : base(dictionary) + { + } + + protected override void ApplyProperty(ComponentModel model, + String key, Object value) + { + String reference = FormattedReferenceExpression(value.ToString()); + Registration.AddParameter(model, key, reference); + } + + private static String FormattedReferenceExpression(String value) + { + if (!ReferenceExpressionUtil.IsReference(value)) + { + value = String.Format("${{{0}}}", value); + } + return value; + } + } +} \ No newline at end of file diff --git a/InversionOfControl/Castle.Windsor/IWindsorContainer.cs b/InversionOfControl/Castle.Windsor/IWindsorContainer.cs index 6aaae2d2f..a6f46af21 100644 --- a/InversionOfControl/Castle.Windsor/IWindsorContainer.cs +++ b/InversionOfControl/Castle.Windsor/IWindsorContainer.cs @@ -18,6 +18,7 @@ namespace Castle.Windsor using System.Collections; using Castle.Core; using Castle.MicroKernel; + using Castle.MicroKernel.Registration; /// /// The IWindsorContainer interface exposes all the @@ -198,6 +199,13 @@ namespace Castle.Windsor IWindsorContainer AddComponentWithLifestyle(String key, IDictionary extendedProperties) where T : class; /// + /// Adds a component to be registered in the container using a fluent interface. + /// + /// The to manage. + /// The + ComponentRegistration AddComponentEx(); + + /// /// Returns a component instance by the key /// /// diff --git a/InversionOfControl/Castle.Windsor/WindsorContainer.cs b/InversionOfControl/Castle.Windsor/WindsorContainer.cs index b569c973a..4c833a426 100644 --- a/InversionOfControl/Castle.Windsor/WindsorContainer.cs +++ b/InversionOfControl/Castle.Windsor/WindsorContainer.cs @@ -19,6 +19,7 @@ namespace Castle.Windsor using Castle.Core; using Castle.MicroKernel; + using Castle.MicroKernel.Registration; using Castle.Windsor.Configuration; using Castle.Windsor.Configuration.Interpreters; @@ -476,6 +477,16 @@ namespace Castle.Windsor } /// + /// Adds a component to be registered in the container using a fluent interface. + /// + /// The to manage. + /// The + public ComponentRegistration AddComponentEx() + { + return new ComponentRegistration(kernel, this); + } + + /// /// Returns a component instance by the key /// /// diff --git a/InversionOfControl/Changes.txt b/InversionOfControl/Changes.txt index 12fbdd122..50943676a 100644 --- a/InversionOfControl/Changes.txt +++ b/InversionOfControl/Changes.txt @@ -1,6 +1,8 @@ RC 4 ==== +- Initial version of MicroKernel/Windsor fluent interface IOC-99 + - Applied patch from Jacob Lewallen improving the locking performance in the DefaultNamingSubsystem under high load. - Applied Philippe Tremblay's patch fixing IOC-94 -- 2.11.4.GIT