Removed untyped contructor from ComponentRegistration and add a protected setter.
[castle.git] / InversionOfControl / Castle.MicroKernel / Facilities / FactorySupport / FactoryActivator.cs
blob9032759b0700903e18a981e287f0336502551d7e
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Facilities.FactorySupport
17 using System;
18 using System.Collections;
19 using System.Reflection;
20 using Castle.Core;
21 using Castle.MicroKernel;
22 using Castle.MicroKernel.ComponentActivator;
23 using Castle.MicroKernel.Facilities;
24 using Castle.MicroKernel.Proxy;
25 using Castle.MicroKernel.SubSystems.Conversion;
27 /// <summary>
28 ///
29 /// </summary>
30 public class FactoryActivator : DefaultComponentActivator
32 public FactoryActivator(ComponentModel model, IKernel kernel, ComponentInstanceDelegate onCreation, ComponentInstanceDelegate onDestruction)
33 : base(model, kernel, onCreation, onDestruction)
37 protected override object Instantiate(CreationContext context)
39 String factoryId = (String)Model.ExtendedProperties["factoryId"];
40 String factoryCreate = (String)Model.ExtendedProperties["factoryCreate"];
42 if (!Kernel.HasComponent(factoryId))
44 String message = String.Format("You have specified a factory ('{2}') " +
45 "for the component '{0}' {1} but the kernel does not have this " +
46 "factory registered",
47 Model.Name, Model.Implementation.FullName, factoryId);
48 throw new FacilityException(message);
51 IHandler factoryHandler = Kernel.GetHandler(factoryId);
53 // Let's find out whether the create method is a static or instance method
55 Type factoryType = factoryHandler.ComponentModel.Implementation;
57 MethodInfo staticCreateMethod =
58 factoryType.GetMethod(factoryCreate,
59 BindingFlags.Public | BindingFlags.Static);
61 if (staticCreateMethod != null)
63 return Create(null, factoryId, staticCreateMethod, factoryCreate, context);
65 else
67 object factoryInstance = Kernel[factoryId];
69 MethodInfo instanceCreateMethod =
70 factoryInstance.GetType().GetMethod(factoryCreate,
71 BindingFlags.Public | BindingFlags.Instance);
73 if (instanceCreateMethod == null)
75 factoryInstance = ProxyUtil.GetUnproxiedInstance(factoryInstance);
77 instanceCreateMethod =
78 factoryInstance.GetType().GetMethod(factoryCreate,
79 BindingFlags.Public | BindingFlags.Instance);
82 if (instanceCreateMethod != null)
84 return Create(factoryInstance, factoryId, instanceCreateMethod, factoryCreate, context);
86 else
88 String message = String.Format("You have specified a factory " +
89 "('{2}' - method to be called: {3}) " +
90 "for the component '{0}' {1} but we couldn't find the creation method" +
91 "(neither instance or static method with the name '{3}')",
92 Model.Name, Model.Implementation.FullName, factoryId, factoryCreate);
93 throw new FacilityException(message);
98 private object Create(object factoryInstance, string factoryId, MethodInfo instanceCreateMethod, string factoryCreate, CreationContext context)
100 object instance;
101 ArrayList methodArgs = new ArrayList();
103 IConversionManager converter = (IConversionManager)
104 Kernel.GetSubSystem(SubSystemConstants.ConversionManagerKey);
108 ParameterInfo[] parameters = instanceCreateMethod.GetParameters();
111 foreach(ParameterInfo parameter in parameters)
113 Type paramType = parameter.ParameterType;
115 DependencyModel depModel;
117 if (converter.IsSupportedAndPrimitiveType(paramType))
119 depModel = new DependencyModel(DependencyType.Parameter, parameter.Name, paramType, false);
121 else
123 depModel = new DependencyModel(DependencyType.Service, parameter.Name, paramType, false);
126 if (!Kernel.Resolver.CanResolve(context, null, Model, depModel))
128 String message = String.Format(
129 "Factory Method {0}.{1} requires an argument '{2}' that could not be resolved",
130 instanceCreateMethod.DeclaringType.FullName, instanceCreateMethod.Name, parameter.Name);
131 throw new FacilityException(message);
134 object arg = Kernel.Resolver.Resolve(context, null, Model, depModel);
136 methodArgs.Add(arg);
139 instance = instanceCreateMethod.Invoke(factoryInstance, methodArgs.ToArray());
141 catch (Exception ex)
143 String message = String.Format("You have specified a factory " +
144 "('{2}' - method to be called: {3}) " +
145 "for the component '{0}' {1} that failed during invoke.",
146 Model.Name, Model.Implementation.FullName, factoryId, factoryCreate);
148 throw new FacilityException(message, ex);
151 if (Model.Interceptors.HasInterceptors)
155 instance = Kernel.ProxyFactory.Create(Kernel, instance, Model, methodArgs.ToArray());
157 catch ( Exception ex )
159 throw new ComponentActivatorException( "FactoryActivator: could not proxy " +
160 instance.GetType().FullName, ex );
164 return instance;