1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
18 using System
.Collections
;
19 using System
.Reflection
;
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
;
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 " +
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
);
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
);
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
)
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);
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
);
139 instance
= instanceCreateMethod
.Invoke(factoryInstance
, methodArgs
.ToArray());
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
);