1 // Copyright 2004-2007 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
.MicroKernel
18 using System
.Collections
;
19 using System
.Collections
.Generic
;
20 using System
.Reflection
;
21 using System
.Runtime
.Serialization
;
23 using Castle
.Core
.Internal
;
24 using Castle
.MicroKernel
.ComponentActivator
;
25 using Castle
.MicroKernel
.Handlers
;
26 using Castle
.MicroKernel
.ModelBuilder
;
27 using Castle
.MicroKernel
.Proxy
;
28 using Castle
.MicroKernel
.Registration
;
29 using Castle
.MicroKernel
.Releasers
;
30 using Castle
.MicroKernel
.Resolvers
;
31 using Castle
.MicroKernel
.SubSystems
.Configuration
;
32 using Castle
.MicroKernel
.SubSystems
.Conversion
;
33 using Castle
.MicroKernel
.SubSystems
.Naming
;
34 using Castle
.MicroKernel
.SubSystems
.Resource
;
37 /// Default implementation of <see cref="IKernel"/>.
38 /// This implementation is complete and also support a kernel
39 /// hierarchy (sub containers).
42 public class DefaultKernel
: KernelEventSupport
, IKernel
, IDeserializationCallback
47 /// The parent kernel, if exists.
49 private IKernel parentKernel
;
52 /// The implementation of <see cref="IHandlerFactory"/>
54 private IHandlerFactory handlerFactory
;
57 /// The implementation of <see cref="IComponentModelBuilder"/>
59 private IComponentModelBuilder modelBuilder
;
62 /// The dependency resolver.
64 private IDependencyResolver resolver
;
67 /// Implements a policy to control component's
68 /// disposal that the usef forgot.
70 private IReleasePolicy releaserPolicy
;
73 /// Holds the implementation of <see cref="IProxyFactory"/>
75 private IProxyFactory proxyFactory
;
78 /// List of <see cref="IFacility"/> registered.
80 private IList facilities
;
83 /// Map of subsystems registered.
85 private IDictionary subsystems
;
88 /// List of sub containers.
90 private IList childKernels
;
97 /// Constructs a DefaultKernel with no component
100 public DefaultKernel()
101 : this(new NotSupportedProxyFactory())
106 /// Constructs a DefaultKernel with the specified
107 /// implementation of <see cref="IProxyFactory"/> and <see cref="IDependencyResolver"/>
109 /// <param name="resolver"></param>
110 /// <param name="proxyFactory"></param>
111 public DefaultKernel(IDependencyResolver resolver
, IProxyFactory proxyFactory
)
114 this.resolver
= resolver
;
115 this.resolver
.Initialize(new DependencyDelegate(RaiseDependencyResolving
));
119 /// Constructs a DefaultKernel with the specified
120 /// implementation of <see cref="IProxyFactory"/>
122 public DefaultKernel(IProxyFactory proxyFactory
)
124 this.proxyFactory
= proxyFactory
;
126 childKernels
= new ArrayList();
127 facilities
= new ArrayList();
128 subsystems
= new Hashtable();
130 RegisterSubSystems();
132 releaserPolicy
= new LifecycledComponentsReleasePolicy();
133 handlerFactory
= new DefaultHandlerFactory(this);
134 modelBuilder
= new DefaultComponentModelBuilder(this);
135 resolver
= new DefaultDependencyResolver(this);
136 resolver
.Initialize(new DependencyDelegate(RaiseDependencyResolving
));
139 public DefaultKernel(SerializationInfo info
, StreamingContext context
)
140 : base(info
, context
)
142 MemberInfo
[] members
= FormatterServices
.GetSerializableMembers(GetType(), context
);
144 object[] kernelmembers
= (object[])info
.GetValue("members", typeof(object[]));
146 FormatterServices
.PopulateObjectMembers(this, members
, kernelmembers
);
153 protected virtual void RegisterSubSystems()
155 AddSubSystem(SubSystemConstants
.ConfigurationStoreKey
,
156 new DefaultConfigurationStore());
158 AddSubSystem(SubSystemConstants
.ConversionManagerKey
,
159 new DefaultConversionManager());
161 AddSubSystem(SubSystemConstants
.NamingKey
,
162 new DefaultNamingSubSystem());
164 AddSubSystem(SubSystemConstants
.ResourceKey
,
165 new DefaultResourceSubSystem());
170 #region IKernel Members
172 public virtual void AddComponent(String key
, Type classType
)
174 AddComponent(key
, classType
, classType
);
178 /// Adds a concrete class
179 /// as a component with the specified <paramref name="lifestyle"/>.
181 /// <param name="key">The key with which to index the component.</param>
182 /// <param name="classType">The <see cref="Type"/> of the component.</param>
183 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
185 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
186 /// attributes, this method will not overwrite that lifestyle. To do that, use the
187 /// <see cref="IKernel.AddComponent(string,Type,LifestyleType,bool)"/> method.
189 /// <exception cref="ArgumentNullException">
190 /// Thrown if <paramref name="key"/> or <paramref name="classType"/>
191 /// are <see langword="null"/>.
193 /// <exception cref="ArgumentException">
194 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
196 public void AddComponent(string key
, Type classType
, LifestyleType lifestyle
)
198 AddComponent(key
, classType
, classType
, lifestyle
);
202 /// Adds a concrete class
203 /// as a component with the specified <paramref name="lifestyle"/>.
205 /// <param name="key">The key with which to index the component.</param>
206 /// <param name="classType">The <see cref="Type"/> of the component.</param>
207 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
208 /// <param name="overwriteLifestyle">
209 /// If <see langword="true"/>, then ignores all other configurations
210 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.
213 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
214 /// attributes, this method will not overwrite that lifestyle. To do that, use the
215 /// <see cref="IKernel.AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
217 /// <exception cref="ArgumentNullException">
218 /// Thrown if <paramref name="key"/> or <paramref name="classType"/>
219 /// are <see langword="null"/>.
221 /// <exception cref="ArgumentException" />
222 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
223 public void AddComponent(string key
, Type classType
, LifestyleType lifestyle
, bool overwriteLifestyle
)
225 AddComponent(key
, classType
, classType
, lifestyle
, overwriteLifestyle
);
228 public virtual void AddComponent(String key
, Type serviceType
, Type classType
)
230 AddComponent(key
, serviceType
, classType
, LifestyleType
.Singleton
);
234 /// Adds a concrete class and an interface
235 /// as a component with the specified <paramref name="lifestyle"/>.
237 /// <param name="key">The key with which to index the component.</param>
238 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
239 /// <param name="classType">The <see cref="Type"/> of the component.</param>
240 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
242 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
243 /// attributes, this method will not overwrite that lifestyle. To do that, use the
244 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
246 /// <exception cref="ArgumentNullException">
247 /// Thrown if <paramref name="key"/>, <paramref name="serviceType"/>, or <paramref name="classType"/>
248 /// are <see langword="null"/>.
250 /// <exception cref="ArgumentException">
251 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
253 public void AddComponent(string key
, Type serviceType
, Type classType
, LifestyleType lifestyle
)
255 AddComponent(key
, serviceType
, classType
, lifestyle
, false);
259 /// Adds a concrete class and an interface
260 /// as a component with the specified <paramref name="lifestyle"/>.
262 /// <param name="key">The key with which to index the component.</param>
263 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
264 /// <param name="classType">The <see cref="Type"/> of the component.</param>
265 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
266 /// <param name="overwriteLifestyle">
267 /// If <see langword="true"/>, then ignores all other configurations
268 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.
271 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
272 /// attributes, this method will not overwrite that lifestyle. To do that, use the
273 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
275 /// <exception cref="ArgumentNullException">
276 /// Thrown if <paramref name="key"/>, <paramref name="serviceType"/>, or <paramref name="classType"/>
277 /// are <see langword="null"/>.
279 /// <exception cref="ArgumentException">
280 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
282 public void AddComponent(string key
, Type serviceType
, Type classType
, LifestyleType lifestyle
,
283 bool overwriteLifestyle
)
285 if (key
== null) throw new ArgumentNullException("key");
286 if (serviceType
== null) throw new ArgumentNullException("serviceType");
287 if (classType
== null) throw new ArgumentNullException("classType");
288 if (LifestyleType
.Undefined
== lifestyle
)
289 throw new ArgumentException("The specified lifestyle must be Thread, Transient, or Singleton.", "lifestyle");
291 ComponentModel model
= ComponentModelBuilder
.BuildModel(key
, serviceType
, classType
, null);
293 if (overwriteLifestyle
|| LifestyleType
.Undefined
== model
.LifestyleType
)
295 model
.LifestyleType
= lifestyle
;
298 RaiseComponentModelCreated(model
);
300 IHandler handler
= HandlerFactory
.Create(model
);
301 RegisterHandler(key
, handler
);
307 /// <param name="key"></param>
308 /// <param name="classType"></param>
309 /// <param name="parameters"></param>
310 public virtual void AddComponentWithExtendedProperties(String key
, Type classType
, IDictionary parameters
)
312 if (key
== null) throw new ArgumentNullException("key");
313 if (parameters
== null) throw new ArgumentNullException("parameters");
314 if (classType
== null) throw new ArgumentNullException("classType");
316 ComponentModel model
= ComponentModelBuilder
.BuildModel(key
, classType
, classType
, parameters
);
317 RaiseComponentModelCreated(model
);
318 IHandler handler
= HandlerFactory
.Create(model
);
319 RegisterHandler(key
, handler
);
325 /// <param name="key"></param>
326 /// <param name="serviceType"></param>
327 /// <param name="classType"></param>
328 /// <param name="parameters"></param>
329 public virtual void AddComponentWithExtendedProperties(String key
, Type serviceType
, Type classType
,
330 IDictionary parameters
)
332 if (key
== null) throw new ArgumentNullException("key");
333 if (parameters
== null) throw new ArgumentNullException("parameters");
334 if (serviceType
== null) throw new ArgumentNullException("serviceType");
335 if (classType
== null) throw new ArgumentNullException("classType");
337 ComponentModel model
= ComponentModelBuilder
.BuildModel(key
, serviceType
, classType
, parameters
);
338 RaiseComponentModelCreated(model
);
339 IHandler handler
= HandlerFactory
.Create(model
);
340 RegisterHandler(key
, handler
);
346 /// <param name="model"></param>
347 public virtual void AddCustomComponent(ComponentModel model
)
349 if (model
== null) throw new ArgumentNullException("model");
351 RaiseComponentModelCreated(model
);
352 IHandler handler
= HandlerFactory
.Create(model
);
354 object skipRegistration
= model
.ExtendedProperties
[ComponentModel
.SkipRegistration
];
356 if (skipRegistration
!= null)
358 RegisterHandler(model
.Name
, handler
, (bool)skipRegistration
);
362 RegisterHandler(model
.Name
, handler
);
367 /// Used mostly by facilities. Adds an instance
368 /// to be used as a component.
370 /// <param name="key"></param>
371 /// <param name="instance"></param>
372 public void AddComponentInstance(String key
, object instance
)
374 if (key
== null) throw new ArgumentNullException("key");
375 if (instance
== null) throw new ArgumentNullException("instance");
377 Type classType
= instance
.GetType();
379 ComponentModel model
= new ComponentModel(key
, classType
, classType
);
380 model
.CustomComponentActivator
= typeof(ExternalInstanceActivator
);
381 model
.ExtendedProperties
["instance"] = instance
;
383 RaiseComponentModelCreated(model
);
384 IHandler handler
= HandlerFactory
.Create(model
);
385 RegisterHandler(key
, handler
);
389 /// Used mostly by facilities. Adds an instance
390 /// to be used as a component.
392 /// <param name="key"></param>
393 /// <param name="serviceType"></param>
394 /// <param name="instance"></param>
395 public void AddComponentInstance(String key
, Type serviceType
, object instance
)
397 AddComponentInstance(key
, serviceType
, instance
.GetType(), instance
);
400 public void AddComponentInstance(string key
, Type serviceType
, Type classType
, object instance
)
402 if (key
== null) throw new ArgumentNullException("key");
403 if (serviceType
== null) throw new ArgumentNullException("serviceType");
404 if (instance
== null) throw new ArgumentNullException("instance");
405 if (classType
== null) throw new ArgumentNullException("classType");
407 ComponentModel model
= new ComponentModel(key
, serviceType
, classType
);
408 model
.CustomComponentActivator
= typeof(ExternalInstanceActivator
);
409 model
.ExtendedProperties
["instance"] = instance
;
411 RaiseComponentModelCreated(model
);
412 IHandler handler
= HandlerFactory
.Create(model
);
413 RegisterHandler(key
, handler
);
417 /// Adds a concrete class as a component
419 public void AddComponent
<T
>()
421 Type classType
= typeof(T
);
422 AddComponent(classType
.FullName
, classType
);
426 /// Adds a concrete class
427 /// as a component with the specified <paramref name="lifestyle"/>.
429 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
431 /// If you have indicated a lifestyle for the specified T using
432 /// attributes, this method will not overwrite that lifestyle. To do that, use the
433 /// <see cref="AddComponent(string,Type,LifestyleType,bool)"/> method.
435 /// <exception cref="ArgumentException">
436 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
438 public void AddComponent
<T
>(LifestyleType lifestyle
)
440 Type classType
= typeof(T
);
441 AddComponent(classType
.FullName
, classType
, lifestyle
);
445 /// Adds a concrete class
446 /// as a component with the specified <paramref name="lifestyle"/>.
448 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
449 /// <param name="overwriteLifestyle">If <see langword="true"/>, then ignores all other configurations
450 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.</param>
452 /// If you have indicated a lifestyle for the specified T using
453 /// attributes, this method will not overwrite that lifestyle. To do that, use the
454 /// <see cref="AddComponent(string,Type,LifestyleType,bool)"/> method.
456 /// <exception cref="ArgumentException"/>
458 /// <paramref name="lifestyle"/>
460 /// <see cref="LifestyleType.Undefined"/>
462 public void AddComponent
<T
>(LifestyleType lifestyle
, bool overwriteLifestyle
)
464 Type classType
= typeof(T
);
465 AddComponent(classType
.FullName
, classType
, lifestyle
, overwriteLifestyle
);
469 /// Adds a concrete class and an interface
472 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
473 public void AddComponent
<T
>(Type serviceType
)
475 Type classType
= typeof(T
);
476 AddComponent(classType
.FullName
, serviceType
, classType
);
480 /// Adds a concrete class and an interface
481 /// as a component with the specified <paramref name="lifestyle"/>.
483 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
484 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
486 /// If you have indicated a lifestyle for the specified T using
487 /// attributes, this method will not overwrite that lifestyle. To do that, use the
488 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
490 /// <exception cref="ArgumentNullException">
491 /// are <see langword="null"/>.
493 /// <exception cref="ArgumentException">
494 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
496 public void AddComponent
<T
>(Type serviceType
, LifestyleType lifestyle
)
498 Type classType
= typeof(T
);
499 AddComponent(classType
.FullName
, serviceType
, classType
, lifestyle
);
503 /// Adds a concrete class and an interface
504 /// as a component with the specified <paramref name="lifestyle"/>.
506 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
507 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
508 /// <param name="overwriteLifestyle">If <see langword="true"/>, then ignores all other configurations
509 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.</param>
511 /// attributes, this method will not overwrite that lifestyle. To do that, use the
512 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
514 /// <exception cref="ArgumentNullException">
515 /// are <see langword="null"/>.
517 /// <exception cref="ArgumentException">
518 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
520 public void AddComponent
<T
>(Type serviceType
, LifestyleType lifestyle
, bool overwriteLifestyle
)
522 Type classType
= typeof(T
);
523 AddComponent(classType
.FullName
, serviceType
, classType
, lifestyle
, overwriteLifestyle
);
527 /// Used mostly by facilities. Adds an instance
528 /// to be used as a component.
530 /// <param name="instance"></param>
531 public void AddComponentInstance
<T
>(object instance
)
533 Type serviceType
= typeof(T
);
534 AddComponentInstance(serviceType
.FullName
, serviceType
, instance
);
538 /// Used mostly by facilities. Adds an instance
539 /// to be used as a component.
541 /// <param name="serviceType"></param>
542 /// <param name="instance"></param>
543 public void AddComponentInstance
<T
>(Type serviceType
, object instance
)
545 Type classType
= typeof(T
);
546 AddComponentInstance(classType
.FullName
, serviceType
, classType
, instance
);
550 /// Adds a component to be registered with the <see cref="IKernel"/>
551 /// using a fluent interface.
553 /// <typeparam name="S">The service <see cref="Type"/> to manage.</typeparam>
554 /// <returns>The <see cref="ComponentRegistration{S,T}"/></returns>
555 public ComponentRegistration
<S
,IKernel
> AddComponentEx
<S
>()
557 return new ComponentRegistration
<S
,IKernel
>(this, this);
561 /// Returns the component instance by the service type
562 /// using dynamic arguments
564 /// <param name="arguments"></param>
565 /// <returns></returns>
566 public T Resolve
<T
>(IDictionary arguments
)
568 Type serviceType
= typeof(T
);
569 return (T
)Resolve(serviceType
, arguments
);
573 /// Returns the component instance by the component key
575 /// <returns></returns>
576 public T Resolve
<T
>()
578 Type serviceType
= typeof(T
);
579 return (T
)Resolve(serviceType
);
583 /// Returns true if the specified component was
584 /// found and could be removed (i.e. no other component depends on it)
586 /// <param name="key">The component's key</param>
587 /// <returns></returns>
588 public virtual bool RemoveComponent(String key
)
590 if (key
== null) throw new ArgumentNullException("key");
592 if (NamingSubSystem
.Contains(key
))
594 IHandler handler
= GetHandler(key
);
596 if (handler
.ComponentModel
.Dependers
.Length
== 0)
598 NamingSubSystem
.UnRegister(key
);
600 IHandler
[] assignableHandlers
= GetAssignableHandlers(handler
.ComponentModel
.Service
);
601 if (assignableHandlers
.Length
> 0)
603 NamingSubSystem
[handler
.ComponentModel
.Service
] = assignableHandlers
[0];
607 NamingSubSystem
.UnRegister(handler
.ComponentModel
.Service
);
610 foreach (ComponentModel model
in handler
.ComponentModel
.Dependents
)
612 model
.RemoveDepender(handler
.ComponentModel
);
615 RaiseComponentUnregistered(key
, handler
);
617 DisposeHandler(handler
);
623 // We can't remove this component as there are
624 // others which depends on it
632 return Parent
.RemoveComponent(key
);
638 public virtual bool HasComponent(String key
)
640 if (key
== null) throw new ArgumentNullException("key");
642 if (NamingSubSystem
.Contains(key
))
649 return Parent
.HasComponent(key
);
655 public virtual bool HasComponent(Type serviceType
)
657 if (serviceType
== null) throw new ArgumentNullException("serviceType");
659 if (NamingSubSystem
.Contains(serviceType
))
664 if (serviceType
.IsGenericType
&& NamingSubSystem
.Contains(serviceType
.GetGenericTypeDefinition()))
671 return Parent
.HasComponent(serviceType
);
677 public virtual object this[String key
]
681 if (key
== null) throw new ArgumentNullException("key");
683 if (!HasComponent(key
))
685 throw new ComponentNotFoundException(key
);
688 IHandler handler
= GetHandler(key
);
690 return ResolveComponent(handler
);
694 public virtual object this[Type service
]
698 if (service
== null) throw new ArgumentNullException("service");
700 if (!HasComponent(service
))
702 throw new ComponentNotFoundException(service
);
705 IHandler handler
= GetHandler(service
);
707 return ResolveComponent(handler
, service
);
712 /// Returns the component instance by the service type
714 public object Resolve(Type service
)
716 if (service
== null) throw new ArgumentNullException("service");
718 return this[service
];
722 /// Returns all the valid component instances by
725 /// <param name="service">The service type</param>
726 /// <param name="arguments">Arguments to resolve the services</param>
727 public Array
ResolveAll(Type service
, IDictionary arguments
)
729 ArrayList list
= new ArrayList();
730 IHandler
[] handlers
= GetAssignableHandlers(service
);
731 foreach (IHandler handler
in handlers
)
733 object component
= ResolveComponent(handler
, service
, arguments
);
736 return list
.ToArray(service
);
740 /// Returns the component instance by the service type
741 /// using dynamic arguments
743 /// <param name="service"></param>
744 /// <param name="arguments"></param>
745 /// <returns></returns>
746 public object Resolve(Type service
, IDictionary arguments
)
748 if (service
== null) throw new ArgumentNullException("service");
749 if (arguments
== null) throw new ArgumentNullException("arguments");
751 if (!HasComponent(service
))
753 throw new ComponentNotFoundException(service
);
756 IHandler handler
= GetHandler(service
);
758 return ResolveComponent(handler
, service
, arguments
);
762 /// Returns the component instance by the component key
763 /// using dynamic arguments
765 /// <param name="key"></param>
766 /// <param name="arguments"></param>
767 /// <returns></returns>
768 public object Resolve(string key
, IDictionary arguments
)
770 if (key
== null) throw new ArgumentNullException("key");
771 if (arguments
== null) throw new ArgumentNullException("arguments");
773 if (!HasComponent(key
))
775 throw new ComponentNotFoundException(key
);
778 IHandler handler
= GetHandler(key
);
780 return ResolveComponent(handler
, arguments
);
784 public void RegisterCustomDependencies(Type service
, IDictionary dependencies
)
786 IHandler handler
= GetHandler(service
);
788 foreach (DictionaryEntry entry
in dependencies
)
790 handler
.AddCustomDependencyValue(entry
.Key
.ToString(), entry
.Value
);
794 public void RegisterCustomDependencies(String key
, IDictionary dependencies
)
796 IHandler handler
= GetHandler(key
);
798 foreach (DictionaryEntry entry
in dependencies
)
800 handler
.AddCustomDependencyValue(entry
.Key
.ToString(), entry
.Value
);
805 /// Returns a component instance by the key
807 /// <param name="key"></param>
808 /// <param name="service"></param>
809 /// <returns></returns>
810 public virtual object Resolve(String key
, Type service
)
812 if (key
== null) throw new ArgumentNullException("key");
813 if (service
== null) throw new ArgumentNullException("service");
815 if (!HasComponent(key
))
817 throw new ComponentNotFoundException(key
);
820 IHandler handler
= GetHandler(key
);
822 return ResolveComponent(handler
, service
);
826 public TService
[] ResolveServices
<TService
>()
828 List
<TService
> services
= new List
<TService
>();
829 IHandler
[] handlers
= GetHandlers(typeof(TService
));
831 foreach (IHandler handler
in handlers
)
833 if (handler
.CurrentState
== HandlerState
.Valid
)
835 services
.Add((TService
)ResolveComponent(handler
));
839 return services
.ToArray();
843 /// Returns a component instance by the key
845 /// <param name="key"></param>
846 /// <param name="service"></param>
847 /// <param name="arguments"></param>
848 /// <returns></returns>
849 public virtual object Resolve(String key
, Type service
, IDictionary arguments
)
851 if (key
== null) throw new ArgumentNullException("key");
852 if (service
== null) throw new ArgumentNullException("service");
854 if (!HasComponent(key
))
856 throw new ComponentNotFoundException(key
);
859 IHandler handler
= GetHandler(key
);
861 return ResolveComponent(handler
, service
, arguments
);
864 public virtual void ReleaseComponent(object instance
)
866 if (ReleasePolicy
.HasTrack(instance
))
868 ReleasePolicy
.Release(instance
);
874 Parent
.ReleaseComponent(instance
);
879 public IHandlerFactory HandlerFactory
881 get { return handlerFactory; }
884 public IComponentModelBuilder ComponentModelBuilder
886 get { return modelBuilder; }
887 set { modelBuilder = value; }
890 public IProxyFactory ProxyFactory
892 get { return proxyFactory; }
893 set { proxyFactory = value; }
896 public virtual IConfigurationStore ConfigurationStore
898 get { return GetSubSystem(SubSystemConstants.ConfigurationStoreKey) as IConfigurationStore; }
899 set { AddSubSystem(SubSystemConstants.ConfigurationStoreKey, value); }
902 public virtual IHandler
GetHandler(String key
)
904 if (key
== null) throw new ArgumentNullException("key");
906 IHandler handler
= NamingSubSystem
.GetHandler(key
);
908 if (handler
== null && Parent
!= null)
910 handler
= WrapParentHandler(Parent
.GetHandler(key
));
916 public virtual IHandler
GetHandler(Type service
)
918 if (service
== null) throw new ArgumentNullException("service");
920 IHandler handler
= NamingSubSystem
.GetHandler(service
);
922 if (handler
== null && service
.IsGenericType
)
924 handler
= NamingSubSystem
.GetHandler(service
.GetGenericTypeDefinition());
927 if (handler
== null && Parent
!= null)
929 handler
= WrapParentHandler(Parent
.GetHandler(service
));
936 /// Return handlers for components that
937 /// implements the specified service.
939 /// <param name="service"></param>
940 /// <returns></returns>
941 public virtual IHandler
[] GetHandlers(Type service
)
943 IHandler
[] result
= NamingSubSystem
.GetHandlers(service
);
945 // a complete generic type, Foo<Bar>, need to check if Foo<T> is registered
946 if (service
.IsGenericType
&& !service
.IsGenericTypeDefinition
)
948 IHandler
[] genericResult
= NamingSubSystem
.GetHandlers(service
.GetGenericTypeDefinition());
950 if (result
.Length
> 0)
952 IHandler
[] mergedResult
= new IHandler
[result
.Length
+ genericResult
.Length
];
953 result
.CopyTo(mergedResult
, 0);
954 genericResult
.CopyTo(mergedResult
, result
.Length
);
955 result
= mergedResult
;
959 result
= genericResult
;
963 // If a parent kernel exists, we merge both results
966 IHandler
[] parentResult
= Parent
.GetHandlers(service
);
968 if (parentResult
.Length
> 0)
970 IHandler
[] newResult
= new IHandler
[result
.Length
+ parentResult
.Length
];
971 result
.CopyTo(newResult
, 0);
972 parentResult
.CopyTo(newResult
, result
.Length
);
981 /// Return handlers for components that
982 /// implements the specified service.
983 /// The check is made using IsAssignableFrom
985 /// <param name="service"></param>
986 /// <returns></returns>
987 public virtual IHandler
[] GetAssignableHandlers(Type service
)
989 return NamingSubSystem
.GetAssignableHandlers(service
);
992 public virtual IReleasePolicy ReleasePolicy
994 get { return releaserPolicy; }
995 set { releaserPolicy = value; }
998 public virtual void AddFacility(String key
, IFacility facility
)
1000 if (key
== null) throw new ArgumentNullException("key");
1001 if (facility
== null) throw new ArgumentNullException("facility");
1003 facility
.Init(this, ConfigurationStore
.GetFacilityConfiguration(key
));
1005 facilities
.Add(facility
);
1009 /// Returns the facilities registered on the kernel.
1011 /// <returns></returns>
1012 public virtual IFacility
[] GetFacilities()
1014 IFacility
[] list
= new IFacility
[facilities
.Count
];
1015 facilities
.CopyTo(list
, 0);
1019 public virtual void AddSubSystem(String key
, ISubSystem subsystem
)
1021 if (key
== null) throw new ArgumentNullException("key");
1022 if (subsystem
== null) throw new ArgumentNullException("facility");
1024 subsystem
.Init(this);
1025 subsystems
[key
] = subsystem
;
1028 public virtual ISubSystem
GetSubSystem(String key
)
1030 if (key
== null) throw new ArgumentNullException("key");
1032 return subsystems
[key
] as ISubSystem
;
1035 public virtual void AddChildKernel(IKernel childKernel
)
1037 if (childKernel
== null) throw new ArgumentNullException("childKernel");
1039 childKernel
.Parent
= this;
1040 childKernels
.Add(childKernel
);
1043 public virtual IKernel Parent
1045 get { return parentKernel; }
1048 // TODO: should the raise add/removed as child kernel methods be invoked from within the subscriber/unsubscribe methods?
1052 if (parentKernel
!= null)
1054 UnsubscribeFromParentKernel();
1055 RaiseRemovedAsChildKernel();
1058 parentKernel
= null;
1062 if ((parentKernel
!= value) && (parentKernel
!= null))
1064 throw new KernelException(
1065 "You can not change the kernel parent once set, use the RemoveChildKernel and AddChildKernel methods together to achieve this.");
1067 parentKernel
= value;
1068 SubscribeToParentKernel();
1069 RaiseAddedAsChildKernel();
1074 public IDependencyResolver Resolver
1076 get { return resolver; }
1079 public virtual IComponentActivator
CreateComponentActivator(ComponentModel model
)
1081 if (model
== null) throw new ArgumentNullException("model");
1083 IComponentActivator activator
;
1085 if (model
.CustomComponentActivator
== null)
1087 activator
= new DefaultComponentActivator(model
, this,
1088 new ComponentInstanceDelegate(RaiseComponentCreated
),
1089 new ComponentInstanceDelegate(RaiseComponentDestroyed
));
1095 activator
= (IComponentActivator
)
1096 Activator
.CreateInstance(model
.CustomComponentActivator
,
1101 new ComponentInstanceDelegate(RaiseComponentCreated
),
1102 new ComponentInstanceDelegate(RaiseComponentDestroyed
)
1107 throw new KernelException("Could not instantiate custom activator", e
);
1115 /// Graph of components and iteractions.
1117 public GraphNode
[] GraphNodes
1121 GraphNode
[] nodes
= new GraphNode
[NamingSubSystem
.ComponentCount
];
1125 IHandler
[] handlers
= NamingSubSystem
.GetHandlers();
1127 foreach (IHandler handler
in handlers
)
1129 nodes
[index
++] = handler
.ComponentModel
;
1136 public virtual void RemoveChildKernel(IKernel childKernel
)
1138 if (childKernel
== null) throw new ArgumentNullException("childKernel");
1139 childKernel
.Parent
= null;
1140 childKernels
.Remove(childKernel
);
1145 #region IServiceProviderEx Members
1148 /// Gets the service object of the specified type.
1152 /// A service object of type serviceType.
1155 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
1156 public object GetService(Type serviceType
)
1158 return Resolve(serviceType
);
1162 /// Gets the service object of the specified type.
1166 /// A service object of type serviceType.
1168 public T GetService
<T
>()
1170 Type serviceType
= typeof(T
);
1171 return (T
)Resolve(serviceType
);
1176 #region IDisposable Members
1179 /// Starts the process of component disposal.
1181 public virtual void Dispose()
1183 DisposeSubKernels();
1184 TerminateFacilities();
1185 DisposeComponentsInstancesWithinTracker();
1187 UnsubscribeFromParentKernel();
1190 private void TerminateFacilities()
1192 foreach (IFacility facility
in facilities
)
1194 facility
.Terminate();
1198 private void DisposeHandlers()
1200 GraphNode
[] nodes
= GraphNodes
;
1201 IVertex
[] vertices
= TopologicalSortAlgo
.Sort(nodes
);
1203 for (int i
= 0; i
< vertices
.Length
; i
++)
1205 ComponentModel model
= (ComponentModel
)vertices
[i
];
1207 // Prevent the removal of a component that belongs
1208 // to other container
1209 if (!NamingSubSystem
.Contains(model
.Name
)) continue;
1211 RemoveComponent(model
.Name
);
1215 private void UnsubscribeFromParentKernel()
1217 if (parentKernel
!= null)
1219 parentKernel
.HandlerRegistered
-= new HandlerDelegate(HandlerRegisteredOnParentKernel
);
1220 parentKernel
.ComponentRegistered
-= new ComponentDataDelegate(RaiseComponentRegistered
);
1221 parentKernel
.ComponentUnregistered
-= new ComponentDataDelegate(RaiseComponentUnregistered
);
1225 private void SubscribeToParentKernel()
1227 if (parentKernel
!= null)
1229 parentKernel
.HandlerRegistered
+= new HandlerDelegate(HandlerRegisteredOnParentKernel
);
1230 parentKernel
.ComponentRegistered
+= new ComponentDataDelegate(RaiseComponentRegistered
);
1231 parentKernel
.ComponentUnregistered
+= new ComponentDataDelegate(RaiseComponentUnregistered
);
1235 private void HandlerRegisteredOnParentKernel(IHandler handler
, ref bool stateChanged
)
1237 RaiseHandlerRegistered(handler
);
1240 private void DisposeComponentsInstancesWithinTracker()
1242 ReleasePolicy
.Dispose();
1245 private void DisposeSubKernels()
1247 foreach (IKernel childKernel
in childKernels
)
1249 childKernel
.Dispose();
1253 protected void DisposeHandler(IHandler handler
)
1255 if (handler
== null) return;
1257 if (handler
is IDisposable
)
1259 ((IDisposable
)handler
).Dispose();
1265 #region Protected members
1267 protected virtual IHandler
WrapParentHandler(IHandler parentHandler
)
1269 if (parentHandler
== null) return null;
1271 // This has a very destructive side-effect. While the goal is to resolve on same-level containers,
1272 // the resolver will invoke GetHandler recursively, leading to stack overflows
1273 // return new ParentHandlerWithChildResolver(parentHandler, Resolver);
1274 return parentHandler
;
1277 protected INamingSubSystem NamingSubSystem
1279 get { return GetSubSystem(SubSystemConstants.NamingKey) as INamingSubSystem; }
1282 protected void RegisterHandler(String key
, IHandler handler
)
1284 RegisterHandler(key
, handler
, false);
1287 protected void RegisterHandler(String key
, IHandler handler
, bool skipRegistration
)
1289 if (!skipRegistration
)
1291 NamingSubSystem
.Register(key
, handler
);
1294 base.RaiseHandlerRegistered(handler
);
1295 base.RaiseComponentRegistered(key
, handler
);
1298 protected object ResolveComponent(IHandler handler
)
1300 return ResolveComponent(handler
, handler
.ComponentModel
.Service
);
1303 protected object ResolveComponent(IHandler handler
, Type service
)
1305 return ResolveComponent(handler
, service
, null);
1308 protected object ResolveComponent(IHandler handler
, IDictionary additionalArguments
)
1310 return ResolveComponent(handler
, handler
.ComponentModel
.Service
, additionalArguments
);
1313 protected object ResolveComponent(IHandler handler
, Type service
, IDictionary additionalArguments
)
1315 CreationContext context
= CreateCreationContext(handler
, service
, additionalArguments
);
1317 object instance
= handler
.Resolve(context
);
1319 ReleasePolicy
.Track(instance
, handler
);
1324 protected CreationContext
CreateCreationContext(IHandler handler
, Type typeToExtractGenericArguments
,
1325 IDictionary additionalArguments
)
1327 return new CreationContext(handler
, typeToExtractGenericArguments
, additionalArguments
);
1332 #region Serialization and Deserialization
1334 public override void GetObjectData(SerializationInfo info
, StreamingContext context
)
1336 base.GetObjectData(info
, context
);
1338 MemberInfo
[] members
= FormatterServices
.GetSerializableMembers(GetType(), context
);
1340 object[] kernelmembers
= FormatterServices
.GetObjectData(this, members
);
1342 info
.AddValue("members", kernelmembers
, typeof(object[]));
1345 void IDeserializationCallback
.OnDeserialization(object sender
)