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
.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() : this(new NotSupportedProxyFactory())
105 /// Constructs a DefaultKernel with the specified
106 /// implementation of <see cref="IProxyFactory"/> and <see cref="IDependencyResolver"/>
108 /// <param name="resolver"></param>
109 /// <param name="proxyFactory"></param>
110 public DefaultKernel(IDependencyResolver resolver
, IProxyFactory proxyFactory
)
113 this.resolver
= resolver
;
114 this.resolver
.Initialize(RaiseDependencyResolving
);
118 /// Constructs a DefaultKernel with the specified
119 /// implementation of <see cref="IProxyFactory"/>
121 public DefaultKernel(IProxyFactory proxyFactory
)
123 this.proxyFactory
= proxyFactory
;
125 childKernels
= new ArrayList();
126 facilities
= new ArrayList();
127 subsystems
= new Hashtable();
129 RegisterSubSystems();
131 releaserPolicy
= new LifecycledComponentsReleasePolicy();
132 handlerFactory
= new DefaultHandlerFactory(this);
133 modelBuilder
= new DefaultComponentModelBuilder(this);
134 resolver
= new DefaultDependencyResolver(this);
135 resolver
.Initialize(new DependencyDelegate(RaiseDependencyResolving
));
138 public DefaultKernel(SerializationInfo info
, StreamingContext context
)
139 : base(info
, context
)
141 MemberInfo
[] members
= FormatterServices
.GetSerializableMembers(GetType(), context
);
143 object[] kernelmembers
= (object[])info
.GetValue("members", typeof(object[]));
145 FormatterServices
.PopulateObjectMembers(this, members
, kernelmembers
);
152 protected virtual void RegisterSubSystems()
154 AddSubSystem(SubSystemConstants
.ConfigurationStoreKey
,
155 new DefaultConfigurationStore());
157 AddSubSystem(SubSystemConstants
.ConversionManagerKey
,
158 new DefaultConversionManager());
160 AddSubSystem(SubSystemConstants
.NamingKey
,
161 new DefaultNamingSubSystem());
163 AddSubSystem(SubSystemConstants
.ResourceKey
,
164 new DefaultResourceSubSystem());
169 #region IKernel Members
171 public virtual void AddComponent(String key
, Type classType
)
173 AddComponent(key
, classType
, classType
);
177 /// Adds a concrete class
178 /// as a component with the specified <paramref name="lifestyle"/>.
180 /// <param name="key">The key with which to index the component.</param>
181 /// <param name="classType">The <see cref="Type"/> of the component.</param>
182 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
184 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
185 /// attributes, this method will not overwrite that lifestyle. To do that, use the
186 /// <see cref="IKernel.AddComponent(string,Type,LifestyleType,bool)"/> method.
188 /// <exception cref="ArgumentNullException">
189 /// Thrown if <paramref name="key"/> or <paramref name="classType"/>
190 /// are <see langword="null"/>.
192 /// <exception cref="ArgumentException">
193 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
195 public void AddComponent(string key
, Type classType
, LifestyleType lifestyle
)
197 AddComponent(key
, classType
, classType
, lifestyle
);
201 /// Adds a concrete class
202 /// as a component with the specified <paramref name="lifestyle"/>.
204 /// <param name="key">The key with which to index the component.</param>
205 /// <param name="classType">The <see cref="Type"/> of the component.</param>
206 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
207 /// <param name="overwriteLifestyle">
208 /// If <see langword="true"/>, then ignores all other configurations
209 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.
212 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
213 /// attributes, this method will not overwrite that lifestyle. To do that, use the
214 /// <see cref="IKernel.AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
216 /// <exception cref="ArgumentNullException">
217 /// Thrown if <paramref name="key"/> or <paramref name="classType"/>
218 /// are <see langword="null"/>.
220 /// <exception cref="ArgumentException" />
221 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
222 public void AddComponent(string key
, Type classType
, LifestyleType lifestyle
, bool overwriteLifestyle
)
224 AddComponent(key
, classType
, classType
, lifestyle
, overwriteLifestyle
);
227 public virtual void AddComponent(String key
, Type serviceType
, Type classType
)
229 AddComponent(key
, serviceType
, classType
, LifestyleType
.Singleton
);
233 /// Adds a concrete class and an interface
234 /// as a component with the specified <paramref name="lifestyle"/>.
236 /// <param name="key">The key with which to index the component.</param>
237 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
238 /// <param name="classType">The <see cref="Type"/> of the component.</param>
239 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
241 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
242 /// attributes, this method will not overwrite that lifestyle. To do that, use the
243 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
245 /// <exception cref="ArgumentNullException">
246 /// Thrown if <paramref name="key"/>, <paramref name="serviceType"/>, or <paramref name="classType"/>
247 /// are <see langword="null"/>.
249 /// <exception cref="ArgumentException">
250 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
252 public void AddComponent(string key
, Type serviceType
, Type classType
, LifestyleType lifestyle
)
254 AddComponent(key
, serviceType
, classType
, lifestyle
, false);
258 /// Adds a concrete class and an interface
259 /// as a component with the specified <paramref name="lifestyle"/>.
261 /// <param name="key">The key with which to index the component.</param>
262 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
263 /// <param name="classType">The <see cref="Type"/> of the component.</param>
264 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
265 /// <param name="overwriteLifestyle">
266 /// If <see langword="true"/>, then ignores all other configurations
267 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.
270 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
271 /// attributes, this method will not overwrite that lifestyle. To do that, use the
272 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
274 /// <exception cref="ArgumentNullException">
275 /// Thrown if <paramref name="key"/>, <paramref name="serviceType"/>, or <paramref name="classType"/>
276 /// are <see langword="null"/>.
278 /// <exception cref="ArgumentException">
279 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
281 public void AddComponent(string key
, Type serviceType
, Type classType
, LifestyleType lifestyle
,
282 bool overwriteLifestyle
)
284 if (key
== null) throw new ArgumentNullException("key");
285 if (serviceType
== null) throw new ArgumentNullException("serviceType");
286 if (classType
== null) throw new ArgumentNullException("classType");
287 if (LifestyleType
.Undefined
== lifestyle
)
288 throw new ArgumentException("The specified lifestyle must be Thread, Transient, or Singleton.", "lifestyle");
290 ComponentModel model
= ComponentModelBuilder
.BuildModel(key
, serviceType
, classType
, null);
292 if (overwriteLifestyle
|| LifestyleType
.Undefined
== model
.LifestyleType
)
294 model
.LifestyleType
= lifestyle
;
297 RaiseComponentModelCreated(model
);
299 IHandler handler
= HandlerFactory
.Create(model
);
300 RegisterHandler(key
, handler
);
306 /// <param name="key"></param>
307 /// <param name="classType"></param>
308 /// <param name="parameters"></param>
309 public virtual void AddComponentWithExtendedProperties(String key
, Type classType
, IDictionary parameters
)
311 if (key
== null) throw new ArgumentNullException("key");
312 if (parameters
== null) throw new ArgumentNullException("parameters");
313 if (classType
== null) throw new ArgumentNullException("classType");
315 ComponentModel model
= ComponentModelBuilder
.BuildModel(key
, classType
, classType
, parameters
);
316 RaiseComponentModelCreated(model
);
317 IHandler handler
= HandlerFactory
.Create(model
);
318 RegisterHandler(key
, handler
);
324 /// <param name="key"></param>
325 /// <param name="serviceType"></param>
326 /// <param name="classType"></param>
327 /// <param name="parameters"></param>
328 public virtual void AddComponentWithExtendedProperties(String key
, Type serviceType
, Type classType
,
329 IDictionary parameters
)
331 if (key
== null) throw new ArgumentNullException("key");
332 if (parameters
== null) throw new ArgumentNullException("parameters");
333 if (serviceType
== null) throw new ArgumentNullException("serviceType");
334 if (classType
== null) throw new ArgumentNullException("classType");
336 ComponentModel model
= ComponentModelBuilder
.BuildModel(key
, serviceType
, classType
, parameters
);
337 RaiseComponentModelCreated(model
);
338 IHandler handler
= HandlerFactory
.Create(model
);
339 RegisterHandler(key
, handler
);
345 /// <param name="model"></param>
346 public virtual void AddCustomComponent(ComponentModel model
)
348 if (model
== null) throw new ArgumentNullException("model");
350 RaiseComponentModelCreated(model
);
351 IHandler handler
= HandlerFactory
.Create(model
);
353 object skipRegistration
= model
.ExtendedProperties
[ComponentModel
.SkipRegistration
];
355 if (skipRegistration
!= null)
357 RegisterHandler(model
.Name
, handler
, (bool)skipRegistration
);
361 RegisterHandler(model
.Name
, handler
);
366 /// Used mostly by facilities. Adds an instance
367 /// to be used as a component.
369 /// <param name="key"></param>
370 /// <param name="instance"></param>
371 public void AddComponentInstance(String key
, object instance
)
373 if (key
== null) throw new ArgumentNullException("key");
374 if (instance
== null) throw new ArgumentNullException("instance");
376 Type classType
= instance
.GetType();
378 ComponentModel model
= new ComponentModel(key
, classType
, classType
);
379 model
.CustomComponentActivator
= typeof(ExternalInstanceActivator
);
380 model
.ExtendedProperties
["instance"] = instance
;
382 RaiseComponentModelCreated(model
);
383 IHandler handler
= HandlerFactory
.Create(model
);
384 RegisterHandler(key
, handler
);
388 /// Used mostly by facilities. Adds an instance
389 /// to be used as a component.
391 /// <param name="key"></param>
392 /// <param name="serviceType"></param>
393 /// <param name="instance"></param>
394 public void AddComponentInstance(String key
, Type serviceType
, object instance
)
396 AddComponentInstance(key
, serviceType
, instance
.GetType(), instance
);
399 public void AddComponentInstance(string key
, Type serviceType
, Type classType
, object instance
)
401 if (key
== null) throw new ArgumentNullException("key");
402 if (serviceType
== null) throw new ArgumentNullException("serviceType");
403 if (instance
== null) throw new ArgumentNullException("instance");
404 if (classType
== null) throw new ArgumentNullException("classType");
406 ComponentModel model
= new ComponentModel(key
, serviceType
, classType
);
407 model
.CustomComponentActivator
= typeof(ExternalInstanceActivator
);
408 model
.ExtendedProperties
["instance"] = instance
;
410 RaiseComponentModelCreated(model
);
411 IHandler handler
= HandlerFactory
.Create(model
);
412 RegisterHandler(key
, handler
);
416 /// Adds a concrete class as a component
418 public void AddComponent
<T
>()
420 Type classType
= typeof(T
);
421 AddComponent(classType
.FullName
, classType
);
425 /// Adds a concrete class
426 /// as a component with the specified <paramref name="lifestyle"/>.
428 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
430 /// If you have indicated a lifestyle for the specified T using
431 /// attributes, this method will not overwrite that lifestyle. To do that, use the
432 /// <see cref="AddComponent(string,Type,LifestyleType,bool)"/> method.
434 /// <exception cref="ArgumentException">
435 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
437 public void AddComponent
<T
>(LifestyleType lifestyle
)
439 Type classType
= typeof(T
);
440 AddComponent(classType
.FullName
, classType
, lifestyle
);
444 /// Adds a concrete class
445 /// as a component with the specified <paramref name="lifestyle"/>.
447 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
448 /// <param name="overwriteLifestyle">If <see langword="true"/>, then ignores all other configurations
449 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.</param>
451 /// If you have indicated a lifestyle for the specified T using
452 /// attributes, this method will not overwrite that lifestyle. To do that, use the
453 /// <see cref="AddComponent(string,Type,LifestyleType,bool)"/> method.
455 /// <exception cref="ArgumentException"/>
457 /// <paramref name="lifestyle"/>
459 /// <see cref="LifestyleType.Undefined"/>
461 public void AddComponent
<T
>(LifestyleType lifestyle
, bool overwriteLifestyle
)
463 Type classType
= typeof(T
);
464 AddComponent(classType
.FullName
, classType
, lifestyle
, overwriteLifestyle
);
468 /// Adds a concrete class and an interface
471 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
472 public void AddComponent
<T
>(Type serviceType
)
474 Type classType
= typeof(T
);
475 AddComponent(classType
.FullName
, serviceType
, classType
);
479 /// Adds a concrete class and an interface
480 /// as a component with the specified <paramref name="lifestyle"/>.
482 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
483 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
485 /// If you have indicated a lifestyle for the specified T using
486 /// attributes, this method will not overwrite that lifestyle. To do that, use the
487 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
489 /// <exception cref="ArgumentNullException">
490 /// are <see langword="null"/>.
492 /// <exception cref="ArgumentException">
493 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
495 public void AddComponent
<T
>(Type serviceType
, LifestyleType lifestyle
)
497 Type classType
= typeof(T
);
498 AddComponent(classType
.FullName
, serviceType
, classType
, lifestyle
);
502 /// Adds a concrete class and an interface
503 /// as a component with the specified <paramref name="lifestyle"/>.
505 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
506 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
507 /// <param name="overwriteLifestyle">If <see langword="true"/>, then ignores all other configurations
508 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.</param>
510 /// attributes, this method will not overwrite that lifestyle. To do that, use the
511 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
513 /// <exception cref="ArgumentNullException">
514 /// are <see langword="null"/>.
516 /// <exception cref="ArgumentException">
517 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
519 public void AddComponent
<T
>(Type serviceType
, LifestyleType lifestyle
, bool overwriteLifestyle
)
521 Type classType
= typeof(T
);
522 AddComponent(classType
.FullName
, serviceType
, classType
, lifestyle
, overwriteLifestyle
);
526 /// Used mostly by facilities. Adds an instance
527 /// to be used as a component.
529 /// <param name="instance"></param>
530 public void AddComponentInstance
<T
>(object instance
)
532 Type serviceType
= typeof(T
);
533 AddComponentInstance(serviceType
.FullName
, serviceType
, instance
);
537 /// Used mostly by facilities. Adds an instance
538 /// to be used as a component.
540 /// <param name="serviceType"></param>
541 /// <param name="instance"></param>
542 public void AddComponentInstance
<T
>(Type serviceType
, object instance
)
544 Type classType
= typeof(T
);
545 AddComponentInstance(classType
.FullName
, serviceType
, classType
, instance
);
549 /// Registers the components described by the <see cref="ComponentRegistration{S}"/>s
550 /// with the <see cref="IKernel"/>.
551 /// <param name="registrations">The component registrations.</param>
552 /// <returns>The kernel.</returns>
554 public IKernel
Register(params IRegistration
[] registrations
)
556 if (registrations
== null)
558 throw new ArgumentNullException("registrations");
561 foreach(IRegistration registration
in registrations
)
563 registration
.Register(this);
570 /// Returns the component instance by the service type
571 /// using dynamic arguments
573 /// <param name="arguments"></param>
574 /// <returns></returns>
575 public T Resolve
<T
>(IDictionary arguments
)
577 Type serviceType
= typeof(T
);
578 return (T
)Resolve(serviceType
, arguments
);
582 /// Returns the component instance by the service type
583 /// using dynamic arguments
585 /// <param name="argumentsAsAnonymousType"></param>
586 /// <returns></returns>
587 public T Resolve
<T
>(object argumentsAsAnonymousType
)
589 return Resolve
<T
>(new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType
));
593 /// Returns the component instance by the component key
595 /// <returns></returns>
596 public T Resolve
<T
>()
598 Type serviceType
= typeof(T
);
599 return (T
)Resolve(serviceType
);
603 /// Returns true if the specified component was
604 /// found and could be removed (i.e. no other component depends on it)
606 /// <param name="key">The component's key</param>
607 /// <returns></returns>
608 public virtual bool RemoveComponent(String key
)
610 if (key
== null) throw new ArgumentNullException("key");
612 if (NamingSubSystem
.Contains(key
))
614 IHandler handler
= GetHandler(key
);
616 if (handler
.ComponentModel
.Dependers
.Length
== 0)
618 NamingSubSystem
.UnRegister(key
);
620 Type service
= handler
.ComponentModel
.Service
;
621 IHandler
[] assignableHandlers
= NamingSubSystem
.GetAssignableHandlers(service
);
622 if (assignableHandlers
.Length
> 0)
624 NamingSubSystem
[handler
.ComponentModel
.Service
] = assignableHandlers
[0];
628 NamingSubSystem
.UnRegister(service
);
631 foreach (ComponentModel model
in handler
.ComponentModel
.Dependents
)
633 model
.RemoveDepender(handler
.ComponentModel
);
636 RaiseComponentUnregistered(key
, handler
);
638 DisposeHandler(handler
);
644 // We can't remove this component as there are
645 // others which depends on it
653 return Parent
.RemoveComponent(key
);
659 public virtual bool HasComponent(String key
)
661 if (key
== null) throw new ArgumentNullException("key");
663 if (NamingSubSystem
.Contains(key
))
670 return Parent
.HasComponent(key
);
676 public virtual bool HasComponent(Type serviceType
)
678 if (serviceType
== null) throw new ArgumentNullException("serviceType");
680 if (NamingSubSystem
.Contains(serviceType
))
685 if (serviceType
.IsGenericType
&& NamingSubSystem
.Contains(serviceType
.GetGenericTypeDefinition()))
692 return Parent
.HasComponent(serviceType
);
698 public virtual object this[String key
]
702 if (key
== null) throw new ArgumentNullException("key");
704 if (!HasComponent(key
))
706 throw new ComponentNotFoundException(key
);
709 IHandler handler
= GetHandler(key
);
711 return ResolveComponent(handler
);
715 public virtual object this[Type service
]
719 if (service
== null) throw new ArgumentNullException("service");
721 if (!HasComponent(service
))
723 throw new ComponentNotFoundException(service
);
726 IHandler handler
= GetHandler(service
);
728 return ResolveComponent(handler
, service
);
733 /// Returns the component instance by the service type
735 public object Resolve(Type service
)
737 if (service
== null) throw new ArgumentNullException("service");
739 return this[service
];
743 /// Returns all the valid component instances by
746 /// <param name="service">The service type</param>
747 /// <param name="arguments">Arguments to resolve the services</param>
748 public Array
ResolveAll(Type service
, IDictionary arguments
)
750 ArrayList list
= new ArrayList();
751 IHandler
[] handlers
= GetAssignableHandlers(service
);
752 foreach (IHandler handler
in handlers
)
754 if(handler
.CurrentState
!=HandlerState
.Valid
)
757 object component
= ResolveComponent(handler
, service
, arguments
);
760 return list
.ToArray(service
);
764 /// Returns all the valid component instances by
767 /// <param name="service">The service type</param>
768 /// <param name="argumentsAsAnonymousType">Arguments to resolve the services</param>
769 public Array
ResolveAll(Type service
, object argumentsAsAnonymousType
)
771 return ResolveAll(service
, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType
));
776 /// Returns component instances that implement TService
778 /// <typeparam name="TService"></typeparam>
779 /// <param name="argumentsAsAnonymousType"></param>
780 /// <returns></returns>
781 public TService
[] ResolveAll
<TService
>(object argumentsAsAnonymousType
)
783 return (TService
[]) ResolveAll(typeof(TService
), argumentsAsAnonymousType
);
787 /// Returns component instances that implement TService
789 /// <typeparam name="TService"></typeparam>
790 /// <param name="arguments"></param>
791 /// <returns></returns>
792 public TService
[] ResolveAll
<TService
>(IDictionary arguments
)
794 return (TService
[])ResolveAll(typeof(TService
), arguments
);
800 /// Returns the component instance by the service type
801 /// using dynamic arguments
803 /// <param name="service"></param>
804 /// <param name="arguments"></param>
805 /// <returns></returns>
806 public object Resolve(Type service
, IDictionary arguments
)
808 if (service
== null) throw new ArgumentNullException("service");
809 if (arguments
== null) throw new ArgumentNullException("arguments");
811 if (!HasComponent(service
))
813 throw new ComponentNotFoundException(service
);
816 IHandler handler
= GetHandler(service
);
818 return ResolveComponent(handler
, service
, arguments
);
822 /// Returns the component instance by the service type
823 /// using dynamic arguments
825 /// <param name="service"></param>
826 /// <param name="argumentsAsAnonymousType"></param>
827 /// <returns></returns>
828 public object Resolve(Type service
, object argumentsAsAnonymousType
)
830 return Resolve(service
, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType
));
834 /// Returns the component instance by the component key
835 /// using dynamic arguments
837 /// <param name="key"></param>
838 /// <param name="arguments"></param>
839 /// <returns></returns>
840 public object Resolve(string key
, IDictionary arguments
)
842 if (key
== null) throw new ArgumentNullException("key");
843 if (arguments
== null) throw new ArgumentNullException("arguments");
845 if (!HasComponent(key
))
847 throw new ComponentNotFoundException(key
);
850 IHandler handler
= GetHandler(key
);
852 return ResolveComponent(handler
, arguments
);
856 /// Returns the component instance by the component key
857 /// using dynamic arguments
859 /// <param name="key"></param>
860 /// <param name="argumentsAsAnonymousType"></param>
861 /// <returns></returns>
862 public object Resolve(string key
, object argumentsAsAnonymousType
)
864 return Resolve(key
, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType
));
868 /// Associates objects with a component handler,
869 /// allowing it to use the specified dictionary
870 /// when resolving dependencies
872 /// <param name="service"></param>
873 /// <param name="dependencies"></param>
874 public void RegisterCustomDependencies(Type service
, IDictionary dependencies
)
876 IHandler handler
= GetHandler(service
);
878 foreach (DictionaryEntry entry
in dependencies
)
880 handler
.AddCustomDependencyValue(entry
.Key
.ToString(), entry
.Value
);
885 /// Associates objects with a component handler,
886 /// allowing it to use the specified dictionary
887 /// when resolving dependencies
889 /// <param name="service"></param>
890 /// <param name="dependenciesAsAnonymousType"></param>
891 public void RegisterCustomDependencies(Type service
, object dependenciesAsAnonymousType
)
893 RegisterCustomDependencies(service
, new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType
));
897 /// Associates objects with a component handler,
898 /// allowing it to use the specified dictionary
899 /// when resolving dependencies
901 /// <param name="key"></param>
902 /// <param name="dependencies"></param>
903 public void RegisterCustomDependencies(String key
, IDictionary dependencies
)
905 IHandler handler
= GetHandler(key
);
907 foreach (DictionaryEntry entry
in dependencies
)
909 handler
.AddCustomDependencyValue(entry
.Key
.ToString(), entry
.Value
);
914 /// Associates objects with a component handler,
915 /// allowing it to use the specified dictionary
916 /// when resolving dependencies
918 /// <param name="key"></param>
919 /// <param name="dependenciesAsAnonymousType"></param>
920 public void RegisterCustomDependencies(String key
, object dependenciesAsAnonymousType
)
922 RegisterCustomDependencies(key
, new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType
));
926 /// Returns a component instance by the key
928 /// <param name="key"></param>
929 /// <param name="service"></param>
930 /// <returns></returns>
931 public virtual object Resolve(String key
, Type service
)
933 if (key
== null) throw new ArgumentNullException("key");
934 if (service
== null) throw new ArgumentNullException("service");
936 if (!HasComponent(key
))
938 throw new ComponentNotFoundException(key
);
941 IHandler handler
= GetHandler(key
);
943 return ResolveComponent(handler
, service
);
948 /// Returns component instances that implement TService
950 /// <typeparam name="TService"></typeparam>
951 /// <returns></returns>
952 public TService
[] ResolveAll
<TService
>()
954 return (TService
[]) ResolveAll(typeof (TService
), new Hashtable());
958 /// Returns a component instance by the key
960 /// <param name="key"></param>
961 /// <param name="service"></param>
962 /// <param name="arguments"></param>
963 /// <returns></returns>
964 public virtual object Resolve(String key
, Type service
, IDictionary arguments
)
966 if (key
== null) throw new ArgumentNullException("key");
967 if (service
== null) throw new ArgumentNullException("service");
969 if (!HasComponent(key
))
971 throw new ComponentNotFoundException(key
);
974 IHandler handler
= GetHandler(key
);
976 return ResolveComponent(handler
, service
, arguments
);
980 /// Resolves the specified key.
982 /// <param name="key">The key.</param>
983 /// <param name="service">The service.</param>
984 /// <param name="argumentsAsAnonymousType">Type of the arguments as anonymous.</param>
985 /// <returns></returns>
986 public virtual object Resolve(String key
, Type service
, object argumentsAsAnonymousType
)
988 return Resolve(key
, service
, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType
));
992 /// Releases a component instance. This allows
993 /// the kernel to execute the proper decomission
994 /// lifecycles on the component instance.
996 /// <param name="instance"></param>
997 public virtual void ReleaseComponent(object instance
)
999 if (ReleasePolicy
.HasTrack(instance
))
1001 ReleasePolicy
.Release(instance
);
1007 Parent
.ReleaseComponent(instance
);
1012 public IHandlerFactory HandlerFactory
1014 get { return handlerFactory; }
1017 public IComponentModelBuilder ComponentModelBuilder
1019 get { return modelBuilder; }
1020 set { modelBuilder = value; }
1023 public IProxyFactory ProxyFactory
1025 get { return proxyFactory; }
1026 set { proxyFactory = value; }
1029 public virtual IConfigurationStore ConfigurationStore
1031 get { return GetSubSystem(SubSystemConstants.ConfigurationStoreKey) as IConfigurationStore; }
1032 set { AddSubSystem(SubSystemConstants.ConfigurationStoreKey, value); }
1035 public virtual IHandler
GetHandler(String key
)
1037 if (key
== null) throw new ArgumentNullException("key");
1039 IHandler handler
= NamingSubSystem
.GetHandler(key
);
1041 if (handler
== null && Parent
!= null)
1043 handler
= WrapParentHandler(Parent
.GetHandler(key
));
1049 public virtual IHandler
GetHandler(Type service
)
1051 if (service
== null) throw new ArgumentNullException("service");
1053 IHandler handler
= NamingSubSystem
.GetHandler(service
);
1055 if (handler
== null && service
.IsGenericType
)
1057 handler
= NamingSubSystem
.GetHandler(service
.GetGenericTypeDefinition());
1060 if (handler
== null && Parent
!= null)
1062 handler
= WrapParentHandler(Parent
.GetHandler(service
));
1069 /// Return handlers for components that
1070 /// implements the specified service.
1072 /// <param name="service"></param>
1073 /// <returns></returns>
1074 public virtual IHandler
[] GetHandlers(Type service
)
1076 IHandler
[] result
= NamingSubSystem
.GetHandlers(service
);
1078 // a complete generic type, Foo<Bar>, need to check if Foo<T> is registered
1079 if (service
.IsGenericType
&& !service
.IsGenericTypeDefinition
)
1081 IHandler
[] genericResult
= NamingSubSystem
.GetHandlers(service
.GetGenericTypeDefinition());
1083 if (result
.Length
> 0)
1085 IHandler
[] mergedResult
= new IHandler
[result
.Length
+ genericResult
.Length
];
1086 result
.CopyTo(mergedResult
, 0);
1087 genericResult
.CopyTo(mergedResult
, result
.Length
);
1088 result
= mergedResult
;
1092 result
= genericResult
;
1096 // If a parent kernel exists, we merge both results
1099 IHandler
[] parentResult
= Parent
.GetHandlers(service
);
1101 if (parentResult
.Length
> 0)
1103 IHandler
[] newResult
= new IHandler
[result
.Length
+ parentResult
.Length
];
1104 result
.CopyTo(newResult
, 0);
1105 parentResult
.CopyTo(newResult
, result
.Length
);
1114 /// Return handlers for components that
1115 /// implements the specified service.
1116 /// The check is made using IsAssignableFrom
1118 /// <param name="service"></param>
1119 /// <returns></returns>
1120 public virtual IHandler
[] GetAssignableHandlers(Type service
)
1122 IHandler
[] result
= NamingSubSystem
.GetAssignableHandlers(service
);
1124 // If a parent kernel exists, we merge both results
1127 IHandler
[] parentResult
= Parent
.GetAssignableHandlers(service
);
1129 if (parentResult
.Length
> 0)
1131 IHandler
[] newResult
= new IHandler
[result
.Length
+ parentResult
.Length
];
1132 result
.CopyTo(newResult
, 0);
1133 parentResult
.CopyTo(newResult
, result
.Length
);
1141 public virtual IReleasePolicy ReleasePolicy
1143 get { return releaserPolicy; }
1144 set { releaserPolicy = value; }
1147 public virtual void AddFacility(String key
, IFacility facility
)
1149 if (key
== null) throw new ArgumentNullException("key");
1150 if (facility
== null) throw new ArgumentNullException("facility");
1152 facility
.Init(this, ConfigurationStore
.GetFacilityConfiguration(key
));
1154 facilities
.Add(facility
);
1157 public void AddFacility
<T
>(String key
) where T
: IFacility
, new()
1159 AddFacility(key
, new T());
1162 public void AddFacility
<T
>() where T
: IFacility
, new()
1164 AddFacility
<T
>(typeof(T
).FullName
);
1168 /// Returns the facilities registered on the kernel.
1170 /// <returns></returns>
1171 public virtual IFacility
[] GetFacilities()
1173 IFacility
[] list
= new IFacility
[facilities
.Count
];
1174 facilities
.CopyTo(list
, 0);
1178 public virtual void AddSubSystem(String key
, ISubSystem subsystem
)
1180 if (key
== null) throw new ArgumentNullException("key");
1181 if (subsystem
== null) throw new ArgumentNullException("facility");
1183 subsystem
.Init(this);
1184 subsystems
[key
] = subsystem
;
1187 public virtual ISubSystem
GetSubSystem(String key
)
1189 if (key
== null) throw new ArgumentNullException("key");
1191 return subsystems
[key
] as ISubSystem
;
1194 public virtual void AddChildKernel(IKernel childKernel
)
1196 if (childKernel
== null) throw new ArgumentNullException("childKernel");
1198 childKernel
.Parent
= this;
1199 childKernels
.Add(childKernel
);
1202 public virtual IKernel Parent
1204 get { return parentKernel; }
1207 // TODO: should the raise add/removed as child kernel methods be invoked from within the subscriber/unsubscribe methods?
1211 if (parentKernel
!= null)
1213 UnsubscribeFromParentKernel();
1214 RaiseRemovedAsChildKernel();
1217 parentKernel
= null;
1221 if ((parentKernel
!= value) && (parentKernel
!= null))
1223 throw new KernelException(
1224 "You can not change the kernel parent once set, use the RemoveChildKernel and AddChildKernel methods together to achieve this.");
1226 parentKernel
= value;
1227 SubscribeToParentKernel();
1228 RaiseAddedAsChildKernel();
1233 public IDependencyResolver Resolver
1235 get { return resolver; }
1238 public virtual IComponentActivator
CreateComponentActivator(ComponentModel model
)
1240 if (model
== null) throw new ArgumentNullException("model");
1242 IComponentActivator activator
;
1244 if (model
.CustomComponentActivator
== null)
1246 activator
= new DefaultComponentActivator(model
, this,
1247 new ComponentInstanceDelegate(RaiseComponentCreated
),
1248 new ComponentInstanceDelegate(RaiseComponentDestroyed
));
1254 activator
= (IComponentActivator
)
1255 Activator
.CreateInstance(model
.CustomComponentActivator
,
1260 new ComponentInstanceDelegate(RaiseComponentCreated
),
1261 new ComponentInstanceDelegate(RaiseComponentDestroyed
)
1266 throw new KernelException("Could not instantiate custom activator", e
);
1274 /// Graph of components and iteractions.
1276 public GraphNode
[] GraphNodes
1280 GraphNode
[] nodes
= new GraphNode
[NamingSubSystem
.ComponentCount
];
1284 IHandler
[] handlers
= NamingSubSystem
.GetHandlers();
1286 foreach (IHandler handler
in handlers
)
1288 nodes
[index
++] = handler
.ComponentModel
;
1295 public virtual void RemoveChildKernel(IKernel childKernel
)
1297 if (childKernel
== null) throw new ArgumentNullException("childKernel");
1298 childKernel
.Parent
= null;
1299 childKernels
.Remove(childKernel
);
1304 #region IServiceProviderEx Members
1307 /// Gets the service object of the specified type.
1311 /// A service object of type serviceType.
1314 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
1315 public object GetService(Type serviceType
)
1317 if (!HasComponent(serviceType
))
1322 return Resolve(serviceType
);
1326 /// Gets the service object of the specified type.
1330 /// A service object of type serviceType.
1332 public T GetService
<T
>() where T
: class
1334 Type serviceType
= typeof(T
);
1336 if (!HasComponent(serviceType
))
1341 return (T
)Resolve(serviceType
);
1346 #region IDisposable Members
1349 /// Starts the process of component disposal.
1351 public virtual void Dispose()
1353 DisposeSubKernels();
1354 TerminateFacilities();
1355 DisposeComponentsInstancesWithinTracker();
1357 UnsubscribeFromParentKernel();
1360 private void TerminateFacilities()
1362 foreach (IFacility facility
in facilities
)
1364 facility
.Terminate();
1368 private void DisposeHandlers()
1370 GraphNode
[] nodes
= GraphNodes
;
1371 IVertex
[] vertices
= TopologicalSortAlgo
.Sort(nodes
);
1373 for (int i
= 0; i
< vertices
.Length
; i
++)
1375 ComponentModel model
= (ComponentModel
)vertices
[i
];
1377 // Prevent the removal of a component that belongs
1378 // to other container
1379 if (!NamingSubSystem
.Contains(model
.Name
)) continue;
1381 RemoveComponent(model
.Name
);
1385 private void UnsubscribeFromParentKernel()
1387 if (parentKernel
!= null)
1389 parentKernel
.HandlerRegistered
-= new HandlerDelegate(HandlerRegisteredOnParentKernel
);
1390 parentKernel
.ComponentRegistered
-= new ComponentDataDelegate(RaiseComponentRegistered
);
1391 parentKernel
.ComponentUnregistered
-= new ComponentDataDelegate(RaiseComponentUnregistered
);
1395 private void SubscribeToParentKernel()
1397 if (parentKernel
!= null)
1399 parentKernel
.HandlerRegistered
+= new HandlerDelegate(HandlerRegisteredOnParentKernel
);
1400 parentKernel
.ComponentRegistered
+= new ComponentDataDelegate(RaiseComponentRegistered
);
1401 parentKernel
.ComponentUnregistered
+= new ComponentDataDelegate(RaiseComponentUnregistered
);
1405 private void HandlerRegisteredOnParentKernel(IHandler handler
, ref bool stateChanged
)
1407 RaiseHandlerRegistered(handler
);
1410 private void DisposeComponentsInstancesWithinTracker()
1412 ReleasePolicy
.Dispose();
1415 private void DisposeSubKernels()
1417 foreach (IKernel childKernel
in childKernels
)
1419 childKernel
.Dispose();
1423 protected void DisposeHandler(IHandler handler
)
1425 if (handler
== null) return;
1427 if (handler
is IDisposable
)
1429 ((IDisposable
)handler
).Dispose();
1435 #region Protected members
1437 protected virtual IHandler
WrapParentHandler(IHandler parentHandler
)
1439 if (parentHandler
== null) return null;
1441 // This has a very destructive side-effect. While the goal is to resolve on same-level containers,
1442 // the resolver will invoke GetHandler recursively, leading to stack overflows
1443 // return new ParentHandlerWithChildResolver(parentHandler, Resolver);
1444 return parentHandler
;
1447 protected INamingSubSystem NamingSubSystem
1449 get { return GetSubSystem(SubSystemConstants.NamingKey) as INamingSubSystem; }
1452 protected void RegisterHandler(String key
, IHandler handler
)
1454 RegisterHandler(key
, handler
, false);
1457 protected void RegisterHandler(String key
, IHandler handler
, bool skipRegistration
)
1459 if (!skipRegistration
)
1461 NamingSubSystem
.Register(key
, handler
);
1464 base.RaiseHandlerRegistered(handler
);
1465 base.RaiseComponentRegistered(key
, handler
);
1468 protected object ResolveComponent(IHandler handler
)
1470 return ResolveComponent(handler
, handler
.ComponentModel
.Service
);
1473 protected object ResolveComponent(IHandler handler
, Type service
)
1475 return ResolveComponent(handler
, service
, null);
1478 protected object ResolveComponent(IHandler handler
, IDictionary additionalArguments
)
1480 return ResolveComponent(handler
, handler
.ComponentModel
.Service
, additionalArguments
);
1483 protected object ResolveComponent(IHandler handler
, Type service
, IDictionary additionalArguments
)
1485 CreationContext context
= CreateCreationContext(handler
, service
, additionalArguments
);
1487 object instance
= handler
.Resolve(context
);
1489 ReleasePolicy
.Track(instance
, handler
);
1494 protected CreationContext
CreateCreationContext(IHandler handler
, Type typeToExtractGenericArguments
,
1495 IDictionary additionalArguments
)
1497 return new CreationContext(handler
, typeToExtractGenericArguments
, additionalArguments
);
1502 #region Serialization and Deserialization
1504 public override void GetObjectData(SerializationInfo info
, StreamingContext context
)
1506 base.GetObjectData(info
, context
);
1508 MemberInfo
[] members
= FormatterServices
.GetSerializableMembers(GetType(), context
);
1510 object[] kernelmembers
= FormatterServices
.GetObjectData(this, members
);
1512 info
.AddValue("members", kernelmembers
, typeof(object[]));
1515 void IDeserializationCallback
.OnDeserialization(object sender
)