Fixing the build, will not add an interceptor twice when it was already added by...
[castle.git] / InversionOfControl / Castle.MicroKernel / DefaultKernel.cs
blob32df115814c32ef7ffaeb0981dd987030599ab2e
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.MicroKernel
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 using System.Reflection;
21 using System.Runtime.Serialization;
22 using Castle.Core;
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;
36 /// <summary>
37 /// Default implementation of <see cref="IKernel"/>.
38 /// This implementation is complete and also support a kernel
39 /// hierarchy (sub containers).
40 /// </summary>
41 [Serializable]
42 public class DefaultKernel : KernelEventSupport, IKernel, IDeserializationCallback
44 #region Fields
46 /// <summary>
47 /// The parent kernel, if exists.
48 /// </summary>
49 private IKernel parentKernel;
51 /// <summary>
52 /// The implementation of <see cref="IHandlerFactory"/>
53 /// </summary>
54 private IHandlerFactory handlerFactory;
56 /// <summary>
57 /// The implementation of <see cref="IComponentModelBuilder"/>
58 /// </summary>
59 private IComponentModelBuilder modelBuilder;
61 /// <summary>
62 /// The dependency resolver.
63 /// </summary>
64 private IDependencyResolver resolver;
66 /// <summary>
67 /// Implements a policy to control component's
68 /// disposal that the usef forgot.
69 /// </summary>
70 private IReleasePolicy releaserPolicy;
72 /// <summary>
73 /// Holds the implementation of <see cref="IProxyFactory"/>
74 /// </summary>
75 private IProxyFactory proxyFactory;
77 /// <summary>
78 /// List of <see cref="IFacility"/> registered.
79 /// </summary>
80 private IList facilities;
82 /// <summary>
83 /// Map of subsystems registered.
84 /// </summary>
85 private IDictionary subsystems;
87 /// <summary>
88 /// List of sub containers.
89 /// </summary>
90 private IList childKernels;
92 #endregion
94 #region Constructors
96 /// <summary>
97 /// Constructs a DefaultKernel with no component
98 /// proxy support.
99 /// </summary>
100 public DefaultKernel() : this(new NotSupportedProxyFactory())
104 /// <summary>
105 /// Constructs a DefaultKernel with the specified
106 /// implementation of <see cref="IProxyFactory"/> and <see cref="IDependencyResolver"/>
107 /// </summary>
108 /// <param name="resolver"></param>
109 /// <param name="proxyFactory"></param>
110 public DefaultKernel(IDependencyResolver resolver, IProxyFactory proxyFactory)
111 : this(proxyFactory)
113 this.resolver = resolver;
114 this.resolver.Initialize(RaiseDependencyResolving);
117 /// <summary>
118 /// Constructs a DefaultKernel with the specified
119 /// implementation of <see cref="IProxyFactory"/>
120 /// </summary>
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);
148 #endregion
150 #region Overridables
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());
167 #endregion
169 #region IKernel Members
171 public virtual void AddComponent(String key, Type classType)
173 AddComponent(key, classType, classType);
176 /// <summary>
177 /// Adds a concrete class
178 /// as a component with the specified <paramref name="lifestyle"/>.
179 /// </summary>
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>
183 /// <remarks>
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.
187 /// </remarks>
188 /// <exception cref="ArgumentNullException">
189 /// Thrown if <paramref name="key"/> or <paramref name="classType"/>
190 /// are <see langword="null"/>.
191 /// </exception>
192 /// <exception cref="ArgumentException">
193 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
194 /// </exception>
195 public void AddComponent(string key, Type classType, LifestyleType lifestyle)
197 AddComponent(key, classType, classType, lifestyle);
200 /// <summary>
201 /// Adds a concrete class
202 /// as a component with the specified <paramref name="lifestyle"/>.
203 /// </summary>
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.
210 /// </param>
211 /// <remarks>
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.
215 /// </remarks>
216 /// <exception cref="ArgumentNullException">
217 /// Thrown if <paramref name="key"/> or <paramref name="classType"/>
218 /// are <see langword="null"/>.
219 /// </exception>
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);
232 /// <summary>
233 /// Adds a concrete class and an interface
234 /// as a component with the specified <paramref name="lifestyle"/>.
235 /// </summary>
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>
240 /// <remarks>
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.
244 /// </remarks>
245 /// <exception cref="ArgumentNullException">
246 /// Thrown if <paramref name="key"/>, <paramref name="serviceType"/>, or <paramref name="classType"/>
247 /// are <see langword="null"/>.
248 /// </exception>
249 /// <exception cref="ArgumentException">
250 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
251 /// </exception>
252 public void AddComponent(string key, Type serviceType, Type classType, LifestyleType lifestyle)
254 AddComponent(key, serviceType, classType, lifestyle, false);
257 /// <summary>
258 /// Adds a concrete class and an interface
259 /// as a component with the specified <paramref name="lifestyle"/>.
260 /// </summary>
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.
268 /// </param>
269 /// <remarks>
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.
273 /// </remarks>
274 /// <exception cref="ArgumentNullException">
275 /// Thrown if <paramref name="key"/>, <paramref name="serviceType"/>, or <paramref name="classType"/>
276 /// are <see langword="null"/>.
277 /// </exception>
278 /// <exception cref="ArgumentException">
279 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
280 /// </exception>
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);
303 /// <summary>
304 ///
305 /// </summary>
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);
321 /// <summary>
322 ///
323 /// </summary>
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);
342 /// <summary>
343 ///
344 /// </summary>
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);
359 else
361 RegisterHandler(model.Name, handler);
365 /// <summary>
366 /// Used mostly by facilities. Adds an instance
367 /// to be used as a component.
368 /// </summary>
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);
387 /// <summary>
388 /// Used mostly by facilities. Adds an instance
389 /// to be used as a component.
390 /// </summary>
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);
415 /// <summary>
416 /// Adds a concrete class as a component
417 /// </summary>
418 public void AddComponent<T>()
420 Type classType = typeof(T);
421 AddComponent(classType.FullName, classType);
424 /// <summary>
425 /// Adds a concrete class
426 /// as a component with the specified <paramref name="lifestyle"/>.
427 /// </summary>
428 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
429 /// <remarks>
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.
433 /// </remarks>
434 /// <exception cref="ArgumentException">
435 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
436 /// </exception>
437 public void AddComponent<T>(LifestyleType lifestyle)
439 Type classType = typeof(T);
440 AddComponent(classType.FullName, classType, lifestyle);
443 /// <summary>
444 /// Adds a concrete class
445 /// as a component with the specified <paramref name="lifestyle"/>.
446 /// </summary>
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>
450 /// <remarks>
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.
454 /// </remarks>
455 /// <exception cref="ArgumentException"/>
456 /// Thrown if
457 /// <paramref name="lifestyle"/>
458 /// is
459 /// <see cref="LifestyleType.Undefined"/>
460 /// .
461 public void AddComponent<T>(LifestyleType lifestyle, bool overwriteLifestyle)
463 Type classType = typeof(T);
464 AddComponent(classType.FullName, classType, lifestyle, overwriteLifestyle);
467 /// <summary>
468 /// Adds a concrete class and an interface
469 /// as a component
470 /// </summary>
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);
478 /// <summary>
479 /// Adds a concrete class and an interface
480 /// as a component with the specified <paramref name="lifestyle"/>.
481 /// </summary>
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>
484 /// <remarks>
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.
488 /// </remarks>
489 /// <exception cref="ArgumentNullException">
490 /// are <see langword="null"/>.
491 /// </exception>
492 /// <exception cref="ArgumentException">
493 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
494 /// </exception>
495 public void AddComponent<T>(Type serviceType, LifestyleType lifestyle)
497 Type classType = typeof(T);
498 AddComponent(classType.FullName, serviceType, classType, lifestyle);
501 /// <summary>
502 /// Adds a concrete class and an interface
503 /// as a component with the specified <paramref name="lifestyle"/>.
504 /// </summary>
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>
509 /// <remarks>
510 /// attributes, this method will not overwrite that lifestyle. To do that, use the
511 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
512 /// </remarks>
513 /// <exception cref="ArgumentNullException">
514 /// are <see langword="null"/>.
515 /// </exception>
516 /// <exception cref="ArgumentException">
517 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
518 /// </exception>
519 public void AddComponent<T>(Type serviceType, LifestyleType lifestyle, bool overwriteLifestyle)
521 Type classType = typeof(T);
522 AddComponent(classType.FullName, serviceType, classType, lifestyle, overwriteLifestyle);
525 /// <summary>
526 /// Used mostly by facilities. Adds an instance
527 /// to be used as a component.
528 /// </summary>
529 /// <param name="instance"></param>
530 public void AddComponentInstance<T>(object instance)
532 Type serviceType = typeof(T);
533 AddComponentInstance(serviceType.FullName, serviceType, instance);
536 /// <summary>
537 /// Used mostly by facilities. Adds an instance
538 /// to be used as a component.
539 /// </summary>
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);
548 /// <summary>
549 /// Adds a component to be registered with the <see cref="IKernel"/>
550 /// using a fluent interface.
551 /// </summary>
552 /// <param name="serviceType">The service type.</param>
553 /// <returns>The <see cref="ComponentRegistration{S,T}"/></returns>
554 public ComponentRegistration<IKernel> AddComponentEx(Type serviceType)
556 return new ComponentRegistration<IKernel>(serviceType, this, this);
559 /// <summary>
560 /// Adds a component to be registered with the <see cref="IKernel"/>
561 /// using a fluent interface.
562 /// </summary>
563 /// <typeparam name="S">The service <see cref="Type"/> to manage.</typeparam>
564 /// <returns>The <see cref="ComponentRegistration{S,T}"/></returns>
565 public ComponentRegistration<S, IKernel> AddComponentEx<S>()
567 return new ComponentRegistration<S, IKernel>(this, this);
570 /// <summary>
571 /// Returns the component instance by the service type
572 /// using dynamic arguments
573 /// </summary>
574 /// <param name="arguments"></param>
575 /// <returns></returns>
576 public T Resolve<T>(IDictionary arguments)
578 Type serviceType = typeof(T);
579 return (T)Resolve(serviceType, arguments);
582 /// <summary>
583 /// Returns the component instance by the service type
584 /// using dynamic arguments
585 /// </summary>
586 /// <param name="argumentsAsAnonymousType"></param>
587 /// <returns></returns>
588 public T Resolve<T>(object argumentsAsAnonymousType)
590 return Resolve<T>(new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
593 /// <summary>
594 /// Returns the component instance by the component key
595 /// </summary>
596 /// <returns></returns>
597 public T Resolve<T>()
599 Type serviceType = typeof(T);
600 return (T)Resolve(serviceType);
603 /// <summary>
604 /// Returns true if the specified component was
605 /// found and could be removed (i.e. no other component depends on it)
606 /// </summary>
607 /// <param name="key">The component's key</param>
608 /// <returns></returns>
609 public virtual bool RemoveComponent(String key)
611 if (key == null) throw new ArgumentNullException("key");
613 if (NamingSubSystem.Contains(key))
615 IHandler handler = GetHandler(key);
617 if (handler.ComponentModel.Dependers.Length == 0)
619 NamingSubSystem.UnRegister(key);
621 IHandler[] assignableHandlers = GetAssignableHandlers(handler.ComponentModel.Service);
622 if (assignableHandlers.Length > 0)
624 NamingSubSystem[handler.ComponentModel.Service] = assignableHandlers[0];
626 else
628 NamingSubSystem.UnRegister(handler.ComponentModel.Service);
631 foreach (ComponentModel model in handler.ComponentModel.Dependents)
633 model.RemoveDepender(handler.ComponentModel);
636 RaiseComponentUnregistered(key, handler);
638 DisposeHandler(handler);
640 return true;
642 else
644 // We can't remove this component as there are
645 // others which depends on it
647 return false;
651 if (Parent != null)
653 return Parent.RemoveComponent(key);
656 return false;
659 public virtual bool HasComponent(String key)
661 if (key == null) throw new ArgumentNullException("key");
663 if (NamingSubSystem.Contains(key))
665 return true;
668 if (Parent != null)
670 return Parent.HasComponent(key);
673 return false;
676 public virtual bool HasComponent(Type serviceType)
678 if (serviceType == null) throw new ArgumentNullException("serviceType");
680 if (NamingSubSystem.Contains(serviceType))
682 return true;
685 if (serviceType.IsGenericType && NamingSubSystem.Contains(serviceType.GetGenericTypeDefinition()))
687 return true;
690 if (Parent != null)
692 return Parent.HasComponent(serviceType);
695 return false;
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);
732 /// <summary>
733 /// Returns the component instance by the service type
734 /// </summary>
735 public object Resolve(Type service)
737 if (service == null) throw new ArgumentNullException("service");
739 return this[service];
742 /// <summary>
743 /// Returns all the valid component instances by
744 /// the service type
745 /// </summary>
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 object component = ResolveComponent(handler, service, arguments);
755 list.Add(component);
757 return list.ToArray(service);
760 /// <summary>
761 /// Returns all the valid component instances by
762 /// the service type
763 /// </summary>
764 /// <param name="service">The service type</param>
765 /// <param name="argumentsAsAnonymousType">Arguments to resolve the services</param>
766 public Array ResolveAll(Type service, object argumentsAsAnonymousType)
768 return ResolveAll(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
771 /// <summary>
772 /// Returns the component instance by the service type
773 /// using dynamic arguments
774 /// </summary>
775 /// <param name="service"></param>
776 /// <param name="arguments"></param>
777 /// <returns></returns>
778 public object Resolve(Type service, IDictionary arguments)
780 if (service == null) throw new ArgumentNullException("service");
781 if (arguments == null) throw new ArgumentNullException("arguments");
783 if (!HasComponent(service))
785 throw new ComponentNotFoundException(service);
788 IHandler handler = GetHandler(service);
790 return ResolveComponent(handler, service, arguments);
793 /// <summary>
794 /// Returns the component instance by the service type
795 /// using dynamic arguments
796 /// </summary>
797 /// <param name="service"></param>
798 /// <param name="argumentsAsAnonymousType"></param>
799 /// <returns></returns>
800 public object Resolve(Type service, object argumentsAsAnonymousType)
802 return Resolve(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
805 /// <summary>
806 /// Returns the component instance by the component key
807 /// using dynamic arguments
808 /// </summary>
809 /// <param name="key"></param>
810 /// <param name="arguments"></param>
811 /// <returns></returns>
812 public object Resolve(string key, IDictionary arguments)
814 if (key == null) throw new ArgumentNullException("key");
815 if (arguments == null) throw new ArgumentNullException("arguments");
817 if (!HasComponent(key))
819 throw new ComponentNotFoundException(key);
822 IHandler handler = GetHandler(key);
824 return ResolveComponent(handler, arguments);
827 /// <summary>
828 /// Returns the component instance by the component key
829 /// using dynamic arguments
830 /// </summary>
831 /// <param name="key"></param>
832 /// <param name="argumentsAsAnonymousType"></param>
833 /// <returns></returns>
834 public object Resolve(string key, object argumentsAsAnonymousType)
836 return Resolve(key, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
839 /// <summary>
840 /// Associates objects with a component handler,
841 /// allowing it to use the specified dictionary
842 /// when resolving dependencies
843 /// </summary>
844 /// <param name="service"></param>
845 /// <param name="dependencies"></param>
846 public void RegisterCustomDependencies(Type service, IDictionary dependencies)
848 IHandler handler = GetHandler(service);
850 foreach (DictionaryEntry entry in dependencies)
852 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
856 /// <summary>
857 /// Associates objects with a component handler,
858 /// allowing it to use the specified dictionary
859 /// when resolving dependencies
860 /// </summary>
861 /// <param name="service"></param>
862 /// <param name="dependenciesAsAnonymousType"></param>
863 public void RegisterCustomDependencies(Type service, object dependenciesAsAnonymousType)
865 RegisterCustomDependencies(service, new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType));
868 /// <summary>
869 /// Associates objects with a component handler,
870 /// allowing it to use the specified dictionary
871 /// when resolving dependencies
872 /// </summary>
873 /// <param name="key"></param>
874 /// <param name="dependencies"></param>
875 public void RegisterCustomDependencies(String key, IDictionary dependencies)
877 IHandler handler = GetHandler(key);
879 foreach (DictionaryEntry entry in dependencies)
881 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
885 /// <summary>
886 /// Associates objects with a component handler,
887 /// allowing it to use the specified dictionary
888 /// when resolving dependencies
889 /// </summary>
890 /// <param name="key"></param>
891 /// <param name="dependenciesAsAnonymousType"></param>
892 public void RegisterCustomDependencies(String key, object dependenciesAsAnonymousType)
894 RegisterCustomDependencies(key, new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType));
897 /// <summary>
898 /// Returns a component instance by the key
899 /// </summary>
900 /// <param name="key"></param>
901 /// <param name="service"></param>
902 /// <returns></returns>
903 public virtual object Resolve(String key, Type service)
905 if (key == null) throw new ArgumentNullException("key");
906 if (service == null) throw new ArgumentNullException("service");
908 if (!HasComponent(key))
910 throw new ComponentNotFoundException(key);
913 IHandler handler = GetHandler(key);
915 return ResolveComponent(handler, service);
919 public TService[] ResolveServices<TService>()
921 List<TService> services = new List<TService>();
922 IHandler[] handlers = GetHandlers(typeof(TService));
924 foreach (IHandler handler in handlers)
926 if (handler.CurrentState == HandlerState.Valid)
928 services.Add((TService)ResolveComponent(handler));
932 return services.ToArray();
935 /// <summary>
936 /// Returns a component instance by the key
937 /// </summary>
938 /// <param name="key"></param>
939 /// <param name="service"></param>
940 /// <param name="arguments"></param>
941 /// <returns></returns>
942 public virtual object Resolve(String key, Type service, IDictionary arguments)
944 if (key == null) throw new ArgumentNullException("key");
945 if (service == null) throw new ArgumentNullException("service");
947 if (!HasComponent(key))
949 throw new ComponentNotFoundException(key);
952 IHandler handler = GetHandler(key);
954 return ResolveComponent(handler, service, arguments);
957 /// <summary>
958 /// Resolves the specified key.
959 /// </summary>
960 /// <param name="key">The key.</param>
961 /// <param name="service">The service.</param>
962 /// <param name="argumentsAsAnonymousType">Type of the arguments as anonymous.</param>
963 /// <returns></returns>
964 public virtual object Resolve(String key, Type service, object argumentsAsAnonymousType)
966 return Resolve(key, service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
969 /// <summary>
970 /// Releases a component instance. This allows
971 /// the kernel to execute the proper decomission
972 /// lifecycles on the component instance.
973 /// </summary>
974 /// <param name="instance"></param>
975 public virtual void ReleaseComponent(object instance)
977 if (ReleasePolicy.HasTrack(instance))
979 ReleasePolicy.Release(instance);
981 else
983 if (Parent != null)
985 Parent.ReleaseComponent(instance);
990 public IHandlerFactory HandlerFactory
992 get { return handlerFactory; }
995 public IComponentModelBuilder ComponentModelBuilder
997 get { return modelBuilder; }
998 set { modelBuilder = value; }
1001 public IProxyFactory ProxyFactory
1003 get { return proxyFactory; }
1004 set { proxyFactory = value; }
1007 public virtual IConfigurationStore ConfigurationStore
1009 get { return GetSubSystem(SubSystemConstants.ConfigurationStoreKey) as IConfigurationStore; }
1010 set { AddSubSystem(SubSystemConstants.ConfigurationStoreKey, value); }
1013 public virtual IHandler GetHandler(String key)
1015 if (key == null) throw new ArgumentNullException("key");
1017 IHandler handler = NamingSubSystem.GetHandler(key);
1019 if (handler == null && Parent != null)
1021 handler = WrapParentHandler(Parent.GetHandler(key));
1024 return handler;
1027 public virtual IHandler GetHandler(Type service)
1029 if (service == null) throw new ArgumentNullException("service");
1031 IHandler handler = NamingSubSystem.GetHandler(service);
1033 if (handler == null && service.IsGenericType)
1035 handler = NamingSubSystem.GetHandler(service.GetGenericTypeDefinition());
1038 if (handler == null && Parent != null)
1040 handler = WrapParentHandler(Parent.GetHandler(service));
1043 return handler;
1046 /// <summary>
1047 /// Return handlers for components that
1048 /// implements the specified service.
1049 /// </summary>
1050 /// <param name="service"></param>
1051 /// <returns></returns>
1052 public virtual IHandler[] GetHandlers(Type service)
1054 IHandler[] result = NamingSubSystem.GetHandlers(service);
1056 // a complete generic type, Foo<Bar>, need to check if Foo<T> is registered
1057 if (service.IsGenericType && !service.IsGenericTypeDefinition)
1059 IHandler[] genericResult = NamingSubSystem.GetHandlers(service.GetGenericTypeDefinition());
1061 if (result.Length > 0)
1063 IHandler[] mergedResult = new IHandler[result.Length + genericResult.Length];
1064 result.CopyTo(mergedResult, 0);
1065 genericResult.CopyTo(mergedResult, result.Length);
1066 result = mergedResult;
1068 else
1070 result = genericResult;
1074 // If a parent kernel exists, we merge both results
1075 if (Parent != null)
1077 IHandler[] parentResult = Parent.GetHandlers(service);
1079 if (parentResult.Length > 0)
1081 IHandler[] newResult = new IHandler[result.Length + parentResult.Length];
1082 result.CopyTo(newResult, 0);
1083 parentResult.CopyTo(newResult, result.Length);
1084 result = newResult;
1088 return result;
1091 /// <summary>
1092 /// Return handlers for components that
1093 /// implements the specified service.
1094 /// The check is made using IsAssignableFrom
1095 /// </summary>
1096 /// <param name="service"></param>
1097 /// <returns></returns>
1098 public virtual IHandler[] GetAssignableHandlers(Type service)
1100 return NamingSubSystem.GetAssignableHandlers(service);
1103 public virtual IReleasePolicy ReleasePolicy
1105 get { return releaserPolicy; }
1106 set { releaserPolicy = value; }
1109 public virtual void AddFacility(String key, IFacility facility)
1111 if (key == null) throw new ArgumentNullException("key");
1112 if (facility == null) throw new ArgumentNullException("facility");
1114 facility.Init(this, ConfigurationStore.GetFacilityConfiguration(key));
1116 facilities.Add(facility);
1119 /// <summary>
1120 /// Returns the facilities registered on the kernel.
1121 /// </summary>
1122 /// <returns></returns>
1123 public virtual IFacility[] GetFacilities()
1125 IFacility[] list = new IFacility[facilities.Count];
1126 facilities.CopyTo(list, 0);
1127 return list;
1130 public virtual void AddSubSystem(String key, ISubSystem subsystem)
1132 if (key == null) throw new ArgumentNullException("key");
1133 if (subsystem == null) throw new ArgumentNullException("facility");
1135 subsystem.Init(this);
1136 subsystems[key] = subsystem;
1139 public virtual ISubSystem GetSubSystem(String key)
1141 if (key == null) throw new ArgumentNullException("key");
1143 return subsystems[key] as ISubSystem;
1146 public virtual void AddChildKernel(IKernel childKernel)
1148 if (childKernel == null) throw new ArgumentNullException("childKernel");
1150 childKernel.Parent = this;
1151 childKernels.Add(childKernel);
1154 public virtual IKernel Parent
1156 get { return parentKernel; }
1159 // TODO: should the raise add/removed as child kernel methods be invoked from within the subscriber/unsubscribe methods?
1161 if (value == null)
1163 if (parentKernel != null)
1165 UnsubscribeFromParentKernel();
1166 RaiseRemovedAsChildKernel();
1169 parentKernel = null;
1171 else
1173 if ((parentKernel != value) && (parentKernel != null))
1175 throw new KernelException(
1176 "You can not change the kernel parent once set, use the RemoveChildKernel and AddChildKernel methods together to achieve this.");
1178 parentKernel = value;
1179 SubscribeToParentKernel();
1180 RaiseAddedAsChildKernel();
1185 public IDependencyResolver Resolver
1187 get { return resolver; }
1190 public virtual IComponentActivator CreateComponentActivator(ComponentModel model)
1192 if (model == null) throw new ArgumentNullException("model");
1194 IComponentActivator activator;
1196 if (model.CustomComponentActivator == null)
1198 activator = new DefaultComponentActivator(model, this,
1199 new ComponentInstanceDelegate(RaiseComponentCreated),
1200 new ComponentInstanceDelegate(RaiseComponentDestroyed));
1202 else
1206 activator = (IComponentActivator)
1207 Activator.CreateInstance(model.CustomComponentActivator,
1208 new object[]
1210 model,
1211 this,
1212 new ComponentInstanceDelegate(RaiseComponentCreated),
1213 new ComponentInstanceDelegate(RaiseComponentDestroyed)
1216 catch (Exception e)
1218 throw new KernelException("Could not instantiate custom activator", e);
1222 return activator;
1225 /// <summary>
1226 /// Graph of components and iteractions.
1227 /// </summary>
1228 public GraphNode[] GraphNodes
1232 GraphNode[] nodes = new GraphNode[NamingSubSystem.ComponentCount];
1234 int index = 0;
1236 IHandler[] handlers = NamingSubSystem.GetHandlers();
1238 foreach (IHandler handler in handlers)
1240 nodes[index++] = handler.ComponentModel;
1243 return nodes;
1247 public virtual void RemoveChildKernel(IKernel childKernel)
1249 if (childKernel == null) throw new ArgumentNullException("childKernel");
1250 childKernel.Parent = null;
1251 childKernels.Remove(childKernel);
1254 #endregion
1256 #region IServiceProviderEx Members
1258 /// <summary>
1259 /// Gets the service object of the specified type.
1260 /// </summary>
1262 /// <returns>
1263 /// A service object of type serviceType.
1264 /// </returns>
1266 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
1267 public object GetService(Type serviceType)
1269 if (!HasComponent(serviceType))
1271 return null;
1274 return Resolve(serviceType);
1277 /// <summary>
1278 /// Gets the service object of the specified type.
1279 /// </summary>
1281 /// <returns>
1282 /// A service object of type serviceType.
1283 /// </returns>
1284 public T GetService<T>() where T : class
1286 Type serviceType = typeof(T);
1288 if (!HasComponent(serviceType))
1290 return null;
1293 return (T)Resolve(serviceType);
1296 #endregion
1298 #region IDisposable Members
1300 /// <summary>
1301 /// Starts the process of component disposal.
1302 /// </summary>
1303 public virtual void Dispose()
1305 DisposeSubKernels();
1306 TerminateFacilities();
1307 DisposeComponentsInstancesWithinTracker();
1308 DisposeHandlers();
1309 UnsubscribeFromParentKernel();
1312 private void TerminateFacilities()
1314 foreach (IFacility facility in facilities)
1316 facility.Terminate();
1320 private void DisposeHandlers()
1322 GraphNode[] nodes = GraphNodes;
1323 IVertex[] vertices = TopologicalSortAlgo.Sort(nodes);
1325 for (int i = 0; i < vertices.Length; i++)
1327 ComponentModel model = (ComponentModel)vertices[i];
1329 // Prevent the removal of a component that belongs
1330 // to other container
1331 if (!NamingSubSystem.Contains(model.Name)) continue;
1333 RemoveComponent(model.Name);
1337 private void UnsubscribeFromParentKernel()
1339 if (parentKernel != null)
1341 parentKernel.HandlerRegistered -= new HandlerDelegate(HandlerRegisteredOnParentKernel);
1342 parentKernel.ComponentRegistered -= new ComponentDataDelegate(RaiseComponentRegistered);
1343 parentKernel.ComponentUnregistered -= new ComponentDataDelegate(RaiseComponentUnregistered);
1347 private void SubscribeToParentKernel()
1349 if (parentKernel != null)
1351 parentKernel.HandlerRegistered += new HandlerDelegate(HandlerRegisteredOnParentKernel);
1352 parentKernel.ComponentRegistered += new ComponentDataDelegate(RaiseComponentRegistered);
1353 parentKernel.ComponentUnregistered += new ComponentDataDelegate(RaiseComponentUnregistered);
1357 private void HandlerRegisteredOnParentKernel(IHandler handler, ref bool stateChanged)
1359 RaiseHandlerRegistered(handler);
1362 private void DisposeComponentsInstancesWithinTracker()
1364 ReleasePolicy.Dispose();
1367 private void DisposeSubKernels()
1369 foreach (IKernel childKernel in childKernels)
1371 childKernel.Dispose();
1375 protected void DisposeHandler(IHandler handler)
1377 if (handler == null) return;
1379 if (handler is IDisposable)
1381 ((IDisposable)handler).Dispose();
1385 #endregion
1387 #region Protected members
1389 protected virtual IHandler WrapParentHandler(IHandler parentHandler)
1391 if (parentHandler == null) return null;
1393 // This has a very destructive side-effect. While the goal is to resolve on same-level containers,
1394 // the resolver will invoke GetHandler recursively, leading to stack overflows
1395 // return new ParentHandlerWithChildResolver(parentHandler, Resolver);
1396 return parentHandler;
1399 protected INamingSubSystem NamingSubSystem
1401 get { return GetSubSystem(SubSystemConstants.NamingKey) as INamingSubSystem; }
1404 protected void RegisterHandler(String key, IHandler handler)
1406 RegisterHandler(key, handler, false);
1409 protected void RegisterHandler(String key, IHandler handler, bool skipRegistration)
1411 if (!skipRegistration)
1413 NamingSubSystem.Register(key, handler);
1416 base.RaiseHandlerRegistered(handler);
1417 base.RaiseComponentRegistered(key, handler);
1420 protected object ResolveComponent(IHandler handler)
1422 return ResolveComponent(handler, handler.ComponentModel.Service);
1425 protected object ResolveComponent(IHandler handler, Type service)
1427 return ResolveComponent(handler, service, null);
1430 protected object ResolveComponent(IHandler handler, IDictionary additionalArguments)
1432 return ResolveComponent(handler, handler.ComponentModel.Service, additionalArguments);
1435 protected object ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments)
1437 CreationContext context = CreateCreationContext(handler, service, additionalArguments);
1439 object instance = handler.Resolve(context);
1441 ReleasePolicy.Track(instance, handler);
1443 return instance;
1446 protected CreationContext CreateCreationContext(IHandler handler, Type typeToExtractGenericArguments,
1447 IDictionary additionalArguments)
1449 return new CreationContext(handler, typeToExtractGenericArguments, additionalArguments);
1452 #endregion
1454 #region Serialization and Deserialization
1456 public override void GetObjectData(SerializationInfo info, StreamingContext context)
1458 base.GetObjectData(info, context);
1460 MemberInfo[] members = FormatterServices.GetSerializableMembers(GetType(), context);
1462 object[] kernelmembers = FormatterServices.GetObjectData(this, members);
1464 info.AddValue("members", kernelmembers, typeof(object[]));
1467 void IDeserializationCallback.OnDeserialization(object sender)
1471 #endregion