User: xtoff
Date: 2009/12/23 10:11 AM

Added:
 /InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/
  DefaultTypedFactoryComponentSelector.cs, Dispose.cs, 
ITypedFactoryComponentSelector.cs, ITypedFactoryMethod.cs, Release.cs, 
Resolve.cs, TypedFactoryInterceptor.cs, TypedFactoryRegistrationExtensions.cs
 /InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/
  TypedFactoryFacilityTake2TestCase.cs

Modified:
 /InversionOfControl/trunk/src/Castle.MicroKernel/
  Castle.MicroKernel-vs2008.csproj
 /InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/
  Empty.cs, FactoryEntry.cs, TypedFactoryFacility.cs
 /InversionOfControl/trunk/src/Castle.Windsor.Tests/
  Castle.Windsor.Tests-vs2008.csproj
 /InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/
  ExternalConfigurationTestCase.cs, TypedFactoryTestCase.cs, 
typedFactory_castle_config.xml

Log:
 - added some new features to TypedFactoryFacility:
        - Access to fluent registration API (via AsFactory() extension method).
        - XML registration is still supported (using existing fallback 
mechanism or new one, if no creation/destruction method is explicitly specified)
        - Any non-void method is 'creation' method, all it's arguments are 
passed as named parameters to kernel.
        - Any void method is 'destruction' method, releasing all it's non-null 
arguments.
        - by default compoments to resolve are matched by type (method's return 
type). When method is named GetSOMETHIG, SOMETHING will be used as component's 
name.
        - default matching may be changed by registering custom implementation 
of ITypedFactoryComponentSelector.
        - when factory implements IDisposable, Dispose will dispose inner 
container used by the factory, and all transient components along with it.
 
 Any feedback on this is appreciated.

File Changes:

Directory: /InversionOfControl/trunk/src/Castle.MicroKernel/
============================================================

File [modified]: Castle.MicroKernel-vs2008.csproj
Delta lines: +36 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/DefaultTypedFactoryComponentSelector.cs
                             (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/DefaultTypedFactoryComponentSelector.cs
     2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,36 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory
+{
+       using System;
+       using System.Reflection;
+
+       using Castle.Core;
+
+       public class DefaultTypedFactoryComponentSelector : 
ITypedFactoryComponentSelector
+       {
+               public Pair<string, Type> SelectComponent(MethodInfo method, 
Type type)
+               {
+                       string componentName = null;
+                       if (method.Name.StartsWith("Get"))
+                       {
+                               componentName = 
method.Name.Substring("get".Length);
+                       }
+                       var componentType = method.ReturnType;
+
+                       return new Pair<string, 
Type>(componentName,componentType);
+               }
+       }
+}

Directory: /InversionOfControl/trunk/src/Castle.Windsor.Tests/
==============================================================

File [modified]: Castle.Windsor.Tests-vs2008.csproj
Delta lines: +26 -12
===================================================================

--- 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/ExternalConfigurationTestCase.cs
  2009-12-23 05:23:04 UTC (rev 6528)
+++ 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/ExternalConfigurationTestCase.cs
  2009-12-23 17:11:42 UTC (rev 6529)
@@ -27,31 +27,31 @@
        [TestFixture]
        public class ExternalConfigurationTestCase
        {
-               private IWindsorContainer _container;
+               private IWindsorContainer container;
 
                [SetUp]
                public void Init()
                {
-                       _container = new 
WindsorContainer(ConfigHelper.ResolveConfigPath("Facilities/TypedFactory/typedFactory_castle_config.xml"));
+                       container = new 
WindsorContainer(ConfigHelper.ResolveConfigPath("Facilities/TypedFactory/typedFactory_castle_config.xml"));
                        
-                       _container.AddFacility( "typedfactory", new 
TypedFactoryFacility() );
+                       container.AddFacility( "typedfactory", new 
TypedFactoryFacility() );
 
-                       _container.AddComponent( "miranda", 
typeof(IProtocolHandler), typeof(MirandaProtocolHandler) );
-                       _container.AddComponent( "messenger", 
typeof(IProtocolHandler), typeof(MessengerProtocolHandler) );
-                       _container.AddComponent( "comp1", 
typeof(IDummyComponent), typeof(Component1) );
-                       _container.AddComponent( "comp2", 
typeof(IDummyComponent), typeof(Component2) );
+                       container.AddComponent( "miranda", 
typeof(IProtocolHandler), typeof(MirandaProtocolHandler) );
+                       container.AddComponent( "messenger", 
typeof(IProtocolHandler), typeof(MessengerProtocolHandler) );
+                       container.AddComponent( "comp1", 
typeof(IDummyComponent), typeof(Component1) );
+                       container.AddComponent( "comp2", 
typeof(IDummyComponent), typeof(Component2) );
                }
 
                [TearDown]
                public void Finish()
                {
-                       _container.Dispose();
+                       container.Dispose();
                }
 
                [Test]
                public void Factory1()
                {
-                       var factory = (IProtocolHandlerFactory1) 
_container["protocolFac1"];
+                       var factory = (IProtocolHandlerFactory1) 
container["protocolFac1"];
 
                        Assert.IsNotNull( factory );
                        
@@ -65,7 +65,7 @@
                [Test]
                public void Factory2()
                {
-                       var factory = (IProtocolHandlerFactory2) 
_container["protocolFac2"];
+                       var factory = (IProtocolHandlerFactory2) 
container["protocolFac2"];
 
                        Assert.IsNotNull( factory );
                        
@@ -83,7 +83,7 @@
                [Test]
                public void Factory3()
                {
-                       var factory = (IComponentFactory1) 
_container["compFactory1"];
+                       var factory = (IComponentFactory1) 
container["compFactory1"];
 
                        Assert.IsNotNull( factory );
                        
@@ -97,7 +97,7 @@
                [Test]
                public void Factory4()
                {
-                       var factory = (IComponentFactory2) 
_container["compFactory2"];
+                       var factory = (IComponentFactory2) 
container["compFactory2"];
                        Assert.IsNotNull( factory );
 
                        var comp1 = (IDummyComponent)factory.Construct("comp1");
@@ -108,6 +108,20 @@
                        Assert.IsTrue( comp2 is Component2 );
                        Assert.IsNotNull( comp2 );
                }
+
+               [Test]
+               public void No_Creation_Or_Destruction_methods_defined()
+               {
+                       var factory = 
(IComponentFactory1)container["NoCreationOrDestructionDefined"];
+
+                       Assert.IsNotNull(factory);
+
+                       var comp1 = factory.Construct();
+                       Assert.IsNotNull(comp1);
+
+                       var comp2 = factory.Construct();
+                       Assert.IsNotNull(comp2);
+               }
        }
 }

Directory: 
/InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/
====================================================================================

File [added]: DefaultTypedFactoryComponentSelector.cs
Delta lines: +35 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/Dispose.cs
                          (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/Dispose.cs
  2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,35 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory
+{
+       using System;
+
+       using Castle.Core.Interceptor;
+
+       public class Dispose : ITypedFactoryMethod
+       {
+               private readonly Action disposeCallback;
+
+               public Dispose(Action disposeCallback)
+               {
+                       this.disposeCallback = disposeCallback;
+               }
+
+               public void Invoke(IInvocation invocation)
+               {
+                       disposeCallback();
+               }
+       }
+}

File [added]: Dispose.cs
Delta lines: +0 -2
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/Empty.cs
    2009-12-23 05:23:04 UTC (rev 6528)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/Empty.cs
    2009-12-23 17:11:42 UTC (rev 6529)
@@ -14,8 +14,6 @@
 
 namespace Castle.Facilities.TypedFactory
 {
-       using System;
-
        public class Empty
        {

File [modified]: Empty.cs
Delta lines: +14 -14
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/FactoryEntry.cs
     2009-12-23 05:23:04 UTC (rev 6528)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/FactoryEntry.cs
     2009-12-23 17:11:42 UTC (rev 6529)
@@ -18,42 +18,42 @@
 
        public class FactoryEntry
        {
-               private String _id;
-               private String _creationMethod;
-               private String _destructionMethod;
-               private Type _factoryInterface;
+               private readonly String id;
+               private readonly String creationMethod;
+               private readonly String destructionMethod;
+               private readonly Type factoryInterface;
 
                public FactoryEntry(String id, Type factoryInterface, String 
creationMethod, String destructionMethod)
                {
-                       if (id == null || id.Length == 0) throw new 
ArgumentNullException("id");
+                       if (string.IsNullOrEmpty(id)) throw new 
ArgumentNullException("id");
                        if (factoryInterface == null) throw new 
ArgumentNullException("factoryInterface");
                        if (!factoryInterface.IsInterface) throw new 
ArgumentException("factoryInterface must be an interface");
-                       if (creationMethod == null || creationMethod.Length == 
0) throw new ArgumentNullException("creationMethod");
+                       if (string.IsNullOrEmpty(creationMethod)) throw new 
ArgumentNullException("creationMethod");
 
-                       _id = id;
-                       _factoryInterface = factoryInterface;
-                       _creationMethod = creationMethod;
-                       _destructionMethod = destructionMethod;
+                       this.id = id;
+                       this.factoryInterface = factoryInterface;
+                       this.creationMethod = creationMethod;
+                       this.destructionMethod = destructionMethod;
                }
 
                public String Id
                {
-                       get { return _id; }
+                       get { return id; }
                }
 
                public Type FactoryInterface
                {
-                       get { return _factoryInterface; }
+                       get { return factoryInterface; }
                }
 
                public String CreationMethod
                {
-                       get { return _creationMethod; }
+                       get { return creationMethod; }
                }
 
                public String DestructionMethod
                {
-                       get { return _destructionMethod; }
+                       get { return destructionMethod; }
                }
        }

File [modified]: FactoryEntry.cs
Delta lines: +37 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/ITypedFactoryComponentSelector.cs
                           (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/ITypedFactoryComponentSelector.cs
   2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,37 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory
+{
+       using System;
+       using System.Reflection;
+
+       using Castle.Core;
+
+       public interface ITypedFactoryComponentSelector
+       {
+               /// <summary>
+               /// Selects one or both of component name and type, for given 
method 
+               /// called on given typed factory type.
+               /// When component should be requested by type only,
+               /// name (first argument of returned pair) should be null.
+               /// When component should be requested by name only,
+               /// type (second argument of returned pair) should be null.
+               /// </summary>
+               /// <param name="method"></param>
+               /// <param name="type"></param>
+               /// <returns></returns>
+               Pair<string, Type> SelectComponent(MethodInfo method, Type 
type);
+       }
+}

File [added]: ITypedFactoryComponentSelector.cs
Delta lines: +27 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/ITypedFactoryMethod.cs
                              (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/ITypedFactoryMethod.cs
      2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,27 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory
+{
+       using Castle.Core.Interceptor;
+
+       public interface ITypedFactoryMethod
+       {
+               /// <summary>
+               /// Performs actual invocation of typed factory method.
+               /// </summary>
+               /// <param name="invocation"></param>
+               void Invoke(IInvocation invocation);
+       }
+}

File [added]: ITypedFactoryMethod.cs
Delta lines: +41 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/Release.cs
                          (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/Release.cs
  2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,41 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory
+{
+       using Castle.Core.Interceptor;
+
+       /// <summary>
+       /// Releases components passed as arguments from the container.
+       /// </summary>
+       public class Release : ITypedFactoryMethod
+       {
+               private readonly IKernel kernel;
+
+               public Release(IKernel kernel)
+               {
+                       this.kernel = kernel;
+               }
+
+               public void Invoke(IInvocation invocation)
+               {
+                       foreach (var argument in invocation.Arguments)
+                       {
+                               if(argument==null) continue;
+
+                               kernel.ReleaseComponent(argument);
+                       }
+               }
+       }
+}

File [added]: Release.cs
Delta lines: +64 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/Resolve.cs
                          (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/Resolve.cs
  2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,64 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory
+{
+       using System.Collections.Generic;
+
+       using Castle.Core.Interceptor;
+
+       /// <summary>
+       /// resolves componet selected by given <see 
cref="ITypedFactoryComponentSelector"/> from the container
+       /// </summary>
+       public class Resolve : ITypedFactoryMethod
+       {
+               private readonly IKernel kernel;
+               private readonly ITypedFactoryComponentSelector selector;
+               public Resolve(IKernel kernel, ITypedFactoryComponentSelector 
selector)
+               {
+                       this.kernel = kernel;
+                       this.selector = selector;
+               }
+
+               public void Invoke(IInvocation invocation)
+               {
+                       var component = 
selector.SelectComponent(invocation.Method, invocation.TargetType);
+                       var arguments = GetArguments(invocation);
+                       if (component.First == null)
+                       {
+                               invocation.ReturnValue = 
kernel.Resolve(component.Second, arguments);
+                               return;
+                       }
+
+                       if (component.Second == null)
+                       {
+                               invocation.ReturnValue = 
kernel.Resolve(component.First, arguments);
+                               return;
+                       }
+
+                       invocation.ReturnValue = 
kernel.Resolve(component.First, component.Second, arguments);
+               }
+
+               private Dictionary<string, object> GetArguments(IInvocation 
invocation)
+               {
+                       var arguments = new Dictionary<string, object>();
+                       var parameters = invocation.Method.GetParameters();
+                       for (int i = 0; i < parameters.Length; i++)
+                       {
+                               arguments.Add(parameters[i].Name, 
invocation.GetArgumentValue(i));
+                       }
+                       return arguments;
+               }
+       }
+}

File [added]: Resolve.cs
Delta lines: +53 -27
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/TypedFactoryFacility.cs
     2009-12-23 05:23:04 UTC (rev 6528)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/TypedFactoryFacility.cs
     2009-12-23 17:11:42 UTC (rev 6529)
@@ -1,4 +1,3 @@
-
 // Copyright 2004-2009 Castle Project - http://www.castleproject.org/
 // 
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,28 +27,36 @@
        /// </summary>
        public class TypedFactoryFacility : AbstractFacility
        {
-               public void AddTypedFactoryEntry( FactoryEntry entry )
+               internal static readonly string InterceptorKey = 
"Castle.TypedFactory.Interceptor";
+
+               [Obsolete("This method is obsolete. Use AsFactory() extension 
method on fluent registration API instead.")]
+               public void AddTypedFactoryEntry(FactoryEntry entry)
                {
-                       ComponentModel model = 
-                               new ComponentModel(entry.Id, 
entry.FactoryInterface, typeof(Empty));
-                       
-                       model.LifestyleType = LifestyleType.Singleton;
+                       var model = new ComponentModel(entry.Id, 
entry.FactoryInterface, typeof(Empty)) { LifestyleType = 
LifestyleType.Singleton };
+
                        model.ExtendedProperties["typed.fac.entry"] = entry;
-                       model.Interceptors.Add( new InterceptorReference( 
typeof(FactoryInterceptor) ) );
+                       model.Interceptors.Add(new 
InterceptorReference(typeof(FactoryInterceptor)));
 
-                       ProxyOptions proxyOptions = 
ProxyUtil.ObtainProxyOptions(model, true);
+                       var proxyOptions = ProxyUtil.ObtainProxyOptions(model, 
true);
                        proxyOptions.OmitTarget = true;
 
-                       Kernel.AddCustomComponent( model );
+                       Kernel.AddCustomComponent(model);
                }
 
                protected override void Init()
                {
-                       Kernel.AddComponent( "typed.fac.interceptor", 
typeof(FactoryInterceptor) );
+                       Kernel.AddComponent(InterceptorKey, 
typeof(TypedFactoryInterceptor), LifestyleType.Transient);
 
-                       ITypeConverter converter = (ITypeConverter)
-                               Kernel.GetSubSystem( 
SubSystemConstants.ConversionManagerKey );
+                       LegacyInit();
+               }
 
+               private void LegacyInit()
+               {
+                       Kernel.AddComponent("typed.fac.interceptor", 
typeof(FactoryInterceptor));
+
+                       var converter = (ITypeConverter)
+                                       
Kernel.GetSubSystem(SubSystemConstants.ConversionManagerKey);
+
                        AddFactories(FacilityConfig, converter);
                }
 
@@ -57,28 +64,47 @@
                {
                        if (facilityConfig != null)
                        {
-                               foreach(IConfiguration config in 
facilityConfig.Children["factories"].Children)
+                               foreach (IConfiguration config in 
facilityConfig.Children["factories"].Children)
                                {
-                                       String id = config.Attributes["id"];
-                                       String creation = 
config.Attributes["creation"];
-                                       String destruction = 
config.Attributes["destruction"];
+                                       var id = config.Attributes["id"];
+                                       var creation = 
config.Attributes["creation"];
+                                       var destruction = 
config.Attributes["destruction"];
 
-                                       Type factoryType = (Type)
-                                               converter.PerformConversion( 
config.Attributes["interface"], typeof(Type) );
-
-                                       try
+                                       var factoryType = 
(Type)converter.PerformConversion(config.Attributes["interface"], typeof(Type));
+                                       if(string.IsNullOrEmpty(creation))
                                        {
-                                               AddTypedFactoryEntry( 
-                                                       new FactoryEntry(id, 
factoryType, creation, destruction) );
+                                               RegisterFactory(id, 
factoryType);
+                                               continue;
                                        }
-                                       catch(Exception)
-                                       {
-                                               string message = "Invalid 
factory entry in configuration";
 
-                                               throw new Exception(message);
-                                       }
+                                       RegisterFactoryLegacy(creation, id, 
factoryType, destruction);
                                }
                        }
                }
+
+               private void RegisterFactory(string id, Type type)
+               {
+                       var model = new ComponentModel(id, type, type) { 
LifestyleType = LifestyleType.Singleton };
+                       model.Interceptors.Add(new 
InterceptorReference(typeof(TypedFactoryInterceptor)));
+                       ProxyUtil.ObtainProxyOptions(model, true).OmitTarget = 
true;
+
+                       Kernel.AddCustomComponent(model);
+               }
+
+               private void RegisterFactoryLegacy(string creation, string id, 
Type factoryType, string destruction)
+               {
+                       try
+                       {
+#pragma warning disable 0618 //call to obsolete method
+                               AddTypedFactoryEntry(new FactoryEntry(id, 
factoryType, creation, destruction));
+#pragma warning restore
+                       }
+                       catch (Exception)
+                       {
+                               string message = "Invalid factory entry in 
configuration";
+
+                               throw new Exception(message);
+                       }
+               }
        }

File [modified]: TypedFactoryFacility.cs
Delta lines: +111 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/TypedFactoryInterceptor.cs
                          (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/TypedFactoryInterceptor.cs
  2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,111 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory
+{
+       using System;
+       using System.Collections.Generic;
+       using System.Linq;
+       using System.Reflection;
+
+       using Castle.Core;
+       using Castle.Core.Interceptor;
+       using Castle.MicroKernel;
+       using Castle.MicroKernel.Facilities.TypedFactory;
+
+       public class TypedFactoryInterceptor : IInterceptor, IOnBehalfAware, 
IDisposable
+       {
+               private readonly IKernel kernel;
+
+               private readonly IDictionary<MethodInfo, ITypedFactoryMethod> 
methods =
+                       new Dictionary<MethodInfo, ITypedFactoryMethod>();
+
+               private ComponentModel target;
+               private bool disposed;
+
+               public TypedFactoryInterceptor(IKernel parent)
+                       : this(parent, new 
DefaultTypedFactoryComponentSelector())
+               {
+                       // if no selector is registered, we'll use the default
+               }
+
+               public TypedFactoryInterceptor(IKernel parent, 
ITypedFactoryComponentSelector componentSelector)
+               {
+                       ComponentSelector = componentSelector;
+                       kernel = new DefaultKernel();
+                       parent.AddChildKernel(kernel);
+               }
+
+               public ITypedFactoryComponentSelector ComponentSelector { get; 
set; }
+
+
+               public void Dispose()
+               {
+                       disposed = true;
+                       kernel.Dispose();
+               }
+               public void Intercept(IInvocation invocation)
+               {
+                       if (disposed)
+                       {
+                               throw new ObjectDisposedException("this", "The 
factory was disposed and can no longer be used.");
+                       }
+
+                       var method = methods[invocation.Method];
+                       method.Invoke(invocation);
+               }
+
+               public void SetInterceptedComponentModel(ComponentModel target)
+               {
+                       this.target = target;
+                       BuildHandlersMap();
+               }
+
+               protected virtual void BuildHandlersMap()
+               {
+                       MethodInfo dispose = GetDisposeMethod();
+
+                       foreach (MethodInfo method in 
target.Service.GetMethods())
+                       {
+                               if (method == dispose)
+                               {
+                                       methods.Add(method, new 
Dispose(Dispose));
+                                       continue;
+                               }
+                               if (IsReleaseMethod(method))
+                               {
+                                       methods.Add(method, new 
Release(kernel));
+                                       continue;
+                               }
+                               //TODO: had collection handling
+                               methods.Add(method, new Resolve(kernel, 
ComponentSelector));
+                       }
+               }
+
+               private MethodInfo GetDisposeMethod()
+               {
+                       if 
(!typeof(IDisposable).IsAssignableFrom(target.Service))
+                       {
+                               return null;
+                       }
+
+                       return 
target.Service.GetInterfaceMap(typeof(IDisposable)).TargetMethods.Single();
+               }
+
+               private bool IsReleaseMethod(MethodInfo methodInfo)
+               {
+                       return methodInfo.ReturnType == typeof(void);
+               }
+       }
+}

File [added]: TypedFactoryInterceptor.cs
Delta lines: +69 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/TypedFactoryRegistrationExtensions.cs
                               (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.MicroKernel/Facilities/TypedFactory/TypedFactoryRegistrationExtensions.cs
       2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,69 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory
+{
+       using System;
+       using System.Linq;
+
+       using Castle.Core;
+       using Castle.Core.Interceptor;
+       using Castle.MicroKernel;
+       using Castle.MicroKernel.Registration;
+
+       public static class TypedFactoryRegistrationExtensions
+       {
+               /// <summary>
+               /// Marks the component as typed factory.
+               /// </summary>
+               /// <typeparam name="S"></typeparam>
+               /// <param name="registration"></param>
+               /// <returns></returns>
+               /// <remarks>
+               /// Only interfaces are legal to use as typed factories. 
Methods with out parameters are not allowed.
+               /// When registering component as typed factory no 
implementation should be provided (in case there is any it will be ignored).
+               /// Typed factories rely on <see cref="IInterceptorSelector"/> 
set internally, so users should not set interceptor selectors explicitly;
+               /// otherwise the factory will not function correctly.
+               /// </remarks>
+               public static ComponentRegistration<S> AsFactory<S>(this 
ComponentRegistration<S> registration)
+               {
+                       if( registration == null )
+                       {
+                               throw new ArgumentNullException( "registration" 
);
+                       }
+
+                       if (registration.ServiceType.IsInterface == false)
+                       {
+                               throw new ComponentRegistrationException(
+                                       string.Format("Type {0} is not an 
interface. Only interfaces may be used as typed factories.",
+                                                     
registration.ServiceType));
+                       }
+
+                       if(HasOutArguments(registration.ServiceType))
+                       {
+                               throw new ComponentRegistrationException(
+                                       string.Format("Type {0} can not be used 
as typed factory because it has methods with 'out' arguments.",
+                                                     
registration.ServiceType));
+                       }
+
+                       return registration.Interceptors( new 
InterceptorReference( TypedFactoryFacility.InterceptorKey ) ).Last;
+
+               }
+
+               private static bool HasOutArguments(Type serviceType)
+               {
+                       return serviceType.GetMethods().Any(m => 
m.GetParameters().Any(p => p.IsOut));
+               }
+       }
+}

File [added]: TypedFactoryRegistrationExtensions.cs
Delta lines: +1 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Castle.Windsor.Tests-vs2008.csproj
        2009-12-23 05:23:04 UTC (rev 6528)
+++ 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Castle.Windsor.Tests-vs2008.csproj
        2009-12-23 17:11:42 UTC (rev 6529)
@@ -284,6 +284,7 @@
     <Compile Include="Facilities\TypedFactory\Factories\IComponentFactory.cs" 
/>
     <Compile 
Include="Facilities\TypedFactory\Factories\IProtocolHandlerFactory.cs" />
     <Compile Include="Facilities\TypedFactory\TypedFactoryTestCase.cs" />
+    <Compile 
Include="Facilities\TypedFactory\TypedFactoryFacilityTake2TestCase.cs" />
     <Compile Include="InterceptorSelectorTestCase.cs" />
     <Compile Include="OpenGenericsTestCase.cs" />

Directory: 
/InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/
======================================================================================

File [modified]: ExternalConfigurationTestCase.cs
Delta lines: +103 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/TypedFactoryFacilityTake2TestCase.cs
                              (rev 0)
+++ 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/TypedFactoryFacilityTake2TestCase.cs
      2009-12-23 17:11:42 UTC (rev 6529)
@@ -0,0 +1,103 @@
+// Copyright 2004-2009 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.Facilities.TypedFactory.Tests
+{
+       using System;
+       using System.Reflection;
+
+       using Castle.Core;
+       using Castle.Facilities.TypedFactory.Tests.Components;
+       using Castle.MicroKernel.Facilities.TypedFactory;
+       using Castle.MicroKernel.Registration;
+       using Castle.Windsor;
+
+       using NUnit.Framework;
+
+       [TestFixture]
+       public class TypedFactoryFacilityTake2TestCase
+       {
+               private WindsorContainer container;
+
+               [SetUp]
+               public void SetUp()
+               {
+                       container = new WindsorContainer();
+                       container.AddFacility<TypedFactoryFacility>();
+                       container.AddComponentLifeStyle<IDummyComponent, 
Component1>(LifestyleType.Transient);
+               }
+
+               [Test]
+               public void Can_resolve_component()
+               {
+                       
container.Register(Component.For<DummyComponentFactory>().AsFactory());
+                       var factory = 
container.Resolve<DummyComponentFactory>();
+
+                       var component = factory.CreateDummyComponent();
+                       Assert.IsNotNull(component);
+               }
+
+               [Test]
+               public void 
Can_resolve_component_by_name_with_default_selector()
+               {
+                       container.Register(
+                               Component.For<IDummyComponent>()
+                                       .ImplementedBy<Component2>()
+                                       .Named("SecondComponent")
+                                       .LifeStyle.Transient,
+                               Component.For<DummyComponentFactory>()
+                                       .AsFactory());
+                       var factory = 
container.Resolve<DummyComponentFactory>();
+
+                       var component = factory.GetSecondComponent();
+                       Assert.IsNotNull(component);
+                       Assert.IsInstanceOf<Component2>(component);
+               }
+
+               [Test]
+               public void Can_use_non_default_selector()
+               {
+                       container.Register(
+                               Component.For<IDummyComponent>()
+                                       .ImplementedBy<Component2>()
+                                       .Named("foo")
+                                       .LifeStyle.Transient,
+                               Component.For<DummyComponentFactory>()
+                                       .AsFactory(),
+                               Component.For<ITypedFactoryComponentSelector>()
+                                       .ImplementedBy<FooSelector>());
+                       var factory = 
container.Resolve<DummyComponentFactory>();
+
+                       var component = factory.GetSecondComponent();
+                       Assert.IsInstanceOf<Component2>(component);
+
+                       component = factory.CreateDummyComponent();
+                       Assert.IsInstanceOf<Component2>(component);
+               }
+       }
+
+       public interface DummyComponentFactory
+       {
+               IDummyComponent CreateDummyComponent();
+               IDummyComponent GetSecondComponent();
+       }
+
+       public class FooSelector:ITypedFactoryComponentSelector
+       {
+               public Pair<string, Type> SelectComponent(MethodInfo method, 
Type type)
+               {
+                       return new Pair<string, Type>("foo", null);
+               }
+       }
+}

File [added]: TypedFactoryFacilityTake2TestCase.cs
Delta lines: +10 -7
===================================================================

--- 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/TypedFactoryTestCase.cs
   2009-12-23 05:23:04 UTC (rev 6528)
+++ 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/TypedFactoryTestCase.cs
   2009-12-23 17:11:42 UTC (rev 6529)
@@ -14,8 +14,6 @@
 
 namespace Castle.Facilities.TypedFactory.Tests
 {
-       using System;
-
        using Castle.Windsor;
 
        using Castle.MicroKernel.SubSystems.Configuration;
@@ -51,10 +49,11 @@
                [Test]
                public void Factory1()
                {
+#pragma warning disable 0618 //call to obsolete method
                        _facility.AddTypedFactoryEntry( 
                                new FactoryEntry(
-                                       "protocolHandlerFactory", 
typeof(IProtocolHandlerFactory1), "Create", "Release") );
-
+                                       "protocolHandlerFactory", 
typeof(IProtocolHandlerFactory1), "Create", "Release"));
+#pragma warning restore
                        _container.AddComponent( "miranda", 
typeof(IProtocolHandler), typeof(MirandaProtocolHandler) );
                        _container.AddComponent( "messenger", 
typeof(IProtocolHandler), typeof(MessengerProtocolHandler) );
 
@@ -73,10 +72,11 @@
                [Test]
                public void Factory2()
                {
+#pragma warning disable 0618 //call to obsolete method
                        _facility.AddTypedFactoryEntry( 
                                new FactoryEntry(
                                "protocolHandlerFactory", 
typeof(IProtocolHandlerFactory2), "Create", "Release") );
-
+#pragma warning restore
                        _container.AddComponent( "miranda", 
typeof(IProtocolHandler), typeof(MirandaProtocolHandler) );
                        _container.AddComponent( "messenger", 
typeof(IProtocolHandler), typeof(MessengerProtocolHandler) );
 
@@ -99,10 +99,11 @@
                [Test]
                public void Factory3()
                {
+#pragma warning disable 0618 //call to obsolete method
                        _facility.AddTypedFactoryEntry( 
                                new FactoryEntry(
                                "compFactory", typeof(IComponentFactory1), 
"Construct", "") );
-
+#pragma warning restore
                        _container.AddComponent( "comp1", 
typeof(IDummyComponent), typeof(Component1) );
                        _container.AddComponent( "comp2", 
typeof(IDummyComponent), typeof(Component2) );
 
@@ -121,9 +122,11 @@
                [Test]
                public void Factory4()
                {
+#pragma warning disable 0618 //call to obsolete method
                        _facility.AddTypedFactoryEntry( 
                                new FactoryEntry(
-                               "compFactory", typeof(IComponentFactory2), 
"Construct", "") );
+                               "compFactory", typeof(IComponentFactory2), 
"Construct", ""));
+#pragma warning restore
 
                        _container.AddComponent( "comp1", 
typeof(IDummyComponent), typeof(Component1) );

File [modified]: TypedFactoryTestCase.cs
Delta lines: +3 -0
===================================================================

--- 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/typedFactory_castle_config.xml
    2009-12-23 05:23:04 UTC (rev 6528)
+++ 
InversionOfControl/trunk/src/Castle.Windsor.Tests/Facilities/TypedFactory/typedFactory_castle_config.xml
    2009-12-23 17:11:42 UTC (rev 6529)
@@ -18,6 +18,9 @@
                          <factory id="protocolFac2" 
                                
interface="Castle.Facilities.TypedFactory.Tests.Factories.IProtocolHandlerFactory2,
 Castle.Windsor.Tests" 
                                creation="Create" destruction="Release" />
+        
+        <factory id="NoCreationOrDestructionDefined"
+                               
interface="Castle.Facilities.TypedFactory.Tests.Factories.IComponentFactory1, 
Castle.Windsor.Tests" />
                        </factories>
                </facility>

File [modified]: typedFactory_castle_config.xml
Delta lines: +0 -0
===================================================================

--

You received this message because you are subscribed to the Google Groups 
"Castle Project Commits" 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-commits?hl=en.


Reply via email to