Added container accessor to Castle.Core
[castle.git] / InversionOfControl / Castle.MicroKernel / DefaultKernel.cs
blob6a7f9f206e2469598d6c5bd3dbbde0bf718e7084
1 // Copyright 2004-2007 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.Releasers;
29 using Castle.MicroKernel.Resolvers;
30 using Castle.MicroKernel.SubSystems.Configuration;
31 using Castle.MicroKernel.SubSystems.Conversion;
32 using Castle.MicroKernel.SubSystems.Naming;
33 using Castle.MicroKernel.SubSystems.Resource;
35 /// <summary>
36 /// Default implementation of <see cref="IKernel"/>.
37 /// This implementation is complete and also support a kernel
38 /// hierarchy (sub containers).
39 /// </summary>
40 [Serializable]
41 public class DefaultKernel : KernelEventSupport, IKernel, IDeserializationCallback
43 #region Fields
45 /// <summary>
46 /// The parent kernel, if exists.
47 /// </summary>
48 private IKernel parentKernel;
50 /// <summary>
51 /// The implementation of <see cref="IHandlerFactory"/>
52 /// </summary>
53 private IHandlerFactory handlerFactory;
55 /// <summary>
56 /// The implementation of <see cref="IComponentModelBuilder"/>
57 /// </summary>
58 private IComponentModelBuilder modelBuilder;
60 /// <summary>
61 /// The dependency resolver.
62 /// </summary>
63 private IDependencyResolver resolver;
65 /// <summary>
66 /// Implements a policy to control component's
67 /// disposal that the usef forgot.
68 /// </summary>
69 private IReleasePolicy releaserPolicy;
71 /// <summary>
72 /// Holds the implementation of <see cref="IProxyFactory"/>
73 /// </summary>
74 private IProxyFactory proxyFactory;
76 /// <summary>
77 /// List of <see cref="IFacility"/> registered.
78 /// </summary>
79 private IList facilities;
81 /// <summary>
82 /// Map of subsystems registered.
83 /// </summary>
84 private IDictionary subsystems;
86 /// <summary>
87 /// List of sub containers.
88 /// </summary>
89 private IList childKernels;
91 #endregion
93 #region Constructors
95 /// <summary>
96 /// Constructs a DefaultKernel with no component
97 /// proxy support.
98 /// </summary>
99 public DefaultKernel()
100 : 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(new DependencyDelegate(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 if (key == null) throw new ArgumentNullException("key");
397 if (serviceType == null) throw new ArgumentNullException("serviceType");
398 if (instance == null) throw new ArgumentNullException("instance");
400 Type classType = instance.GetType();
402 ComponentModel model = new ComponentModel(key, serviceType, classType);
403 model.CustomComponentActivator = typeof(ExternalInstanceActivator);
404 model.ExtendedProperties["instance"] = instance;
406 RaiseComponentModelCreated(model);
407 IHandler handler = HandlerFactory.Create(model);
408 RegisterHandler(key, handler);
411 /// <summary>
412 /// Adds a concrete class as a component
413 /// </summary>
414 public void AddComponent<T>()
416 Type classType = typeof(T);
417 AddComponent(classType.FullName, classType);
420 /// <summary>
421 /// Adds a concrete class
422 /// as a component with the specified <paramref name="lifestyle"/>.
423 /// </summary>
424 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
425 /// <remarks>
426 /// If you have indicated a lifestyle for the specified T using
427 /// attributes, this method will not overwrite that lifestyle. To do that, use the
428 /// <see cref="AddComponent(string,Type,LifestyleType,bool)"/> method.
429 /// </remarks>
430 /// <exception cref="ArgumentException">
431 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
432 /// </exception>
433 public void AddComponent<T>(LifestyleType lifestyle)
435 Type classType = typeof(T);
436 AddComponent(classType.FullName, classType, lifestyle);
439 /// <summary>
440 /// Adds a concrete class
441 /// as a component with the specified <paramref name="lifestyle"/>.
442 /// </summary>
443 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
444 /// <param name="overwriteLifestyle">If <see langword="true"/>, then ignores all other configurations
445 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.</param>
446 /// <remarks>
447 /// If you have indicated a lifestyle for the specified T using
448 /// attributes, this method will not overwrite that lifestyle. To do that, use the
449 /// <see cref="AddComponent(string,Type,LifestyleType,bool)"/> method.
450 /// </remarks>
451 /// <exception cref="ArgumentException"/>
452 /// Thrown if
453 /// <paramref name="lifestyle"/>
454 /// is
455 /// <see cref="LifestyleType.Undefined"/>
456 /// .
457 public void AddComponent<T>(LifestyleType lifestyle, bool overwriteLifestyle)
459 Type classType = typeof(T);
460 AddComponent(classType.FullName, classType, lifestyle, overwriteLifestyle);
463 /// <summary>
464 /// Adds a concrete class and an interface
465 /// as a component
466 /// </summary>
467 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
468 public void AddComponent<T>(Type serviceType)
470 Type classType = typeof(T);
471 AddComponent(classType.FullName, serviceType, classType);
474 /// <summary>
475 /// Adds a concrete class and an interface
476 /// as a component with the specified <paramref name="lifestyle"/>.
477 /// </summary>
478 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
479 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
480 /// <remarks>
481 /// If you have indicated a lifestyle for the specified T using
482 /// attributes, this method will not overwrite that lifestyle. To do that, use the
483 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
484 /// </remarks>
485 /// <exception cref="ArgumentNullException">
486 /// are <see langword="null"/>.
487 /// </exception>
488 /// <exception cref="ArgumentException">
489 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
490 /// </exception>
491 public void AddComponent<T>(Type serviceType, LifestyleType lifestyle)
493 Type classType = typeof(T);
494 AddComponent(classType.FullName, serviceType, classType, lifestyle);
497 /// <summary>
498 /// Adds a concrete class and an interface
499 /// as a component with the specified <paramref name="lifestyle"/>.
500 /// </summary>
501 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
502 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
503 /// <param name="overwriteLifestyle">If <see langword="true"/>, then ignores all other configurations
504 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.</param>
505 /// <remarks>
506 /// attributes, this method will not overwrite that lifestyle. To do that, use the
507 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
508 /// </remarks>
509 /// <exception cref="ArgumentNullException">
510 /// are <see langword="null"/>.
511 /// </exception>
512 /// <exception cref="ArgumentException">
513 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
514 /// </exception>
515 public void AddComponent<T>(Type serviceType, LifestyleType lifestyle, bool overwriteLifestyle)
517 Type classType = typeof(T);
518 AddComponent(classType.FullName, serviceType, classType, lifestyle, overwriteLifestyle);
521 /// <summary>
522 /// Used mostly by facilities. Adds an instance
523 /// to be used as a component.
524 /// </summary>
525 /// <param name="instance"></param>
526 public void AddComponentInstance<T>(object instance)
528 Type serviceType = typeof(T);
529 AddComponentInstance(serviceType.FullName, instance);
532 /// <summary>
533 /// Used mostly by facilities. Adds an instance
534 /// to be used as a component.
535 /// </summary>
536 /// <param name="serviceType"></param>
537 /// <param name="instance"></param>
538 public void AddComponentInstance<T>(Type serviceType, object instance)
540 Type classType = typeof(T);
541 AddComponentInstance(classType.FullName, serviceType, instance);
544 /// <summary>
545 /// Returns the component instance by the service type
546 /// using dynamic arguments
547 /// </summary>
548 /// <param name="arguments"></param>
549 /// <returns></returns>
550 public T Resolve<T>(IDictionary arguments)
552 Type serviceType = typeof(T);
553 return (T) Resolve(serviceType, arguments);
556 /// <summary>
557 /// Returns the component instance by the component key
558 /// </summary>
559 /// <returns></returns>
560 public T Resolve<T>()
562 Type serviceType = typeof(T);
563 return (T) Resolve(serviceType);
566 /// <summary>
567 /// Returns true if the specified component was
568 /// found and could be removed (i.e. no other component depends on it)
569 /// </summary>
570 /// <param name="key">The component's key</param>
571 /// <returns></returns>
572 public virtual bool RemoveComponent(String key)
574 if (key == null) throw new ArgumentNullException("key");
576 if (NamingSubSystem.Contains(key))
578 IHandler handler = GetHandler(key);
580 if (handler.ComponentModel.Dependers.Length == 0)
582 NamingSubSystem.UnRegister(key);
584 IHandler[] assignableHandlers = GetAssignableHandlers(handler.ComponentModel.Service);
585 if (assignableHandlers.Length > 0)
587 NamingSubSystem[handler.ComponentModel.Service] = assignableHandlers[0];
589 else
591 NamingSubSystem.UnRegister(handler.ComponentModel.Service);
594 foreach(ComponentModel model in handler.ComponentModel.Dependents)
596 model.RemoveDepender(handler.ComponentModel);
599 RaiseComponentUnregistered(key, handler);
601 DisposeHandler(handler);
603 return true;
605 else
607 // We can't remove this component as there are
608 // others which depends on it
610 return false;
614 if (Parent != null)
616 return Parent.RemoveComponent(key);
619 return false;
622 public virtual bool HasComponent(String key)
624 if (key == null) throw new ArgumentNullException("key");
626 if (NamingSubSystem.Contains(key))
628 return true;
631 if (Parent != null)
633 return Parent.HasComponent(key);
636 return false;
639 public virtual bool HasComponent(Type serviceType)
641 if (serviceType == null) throw new ArgumentNullException("serviceType");
643 if (NamingSubSystem.Contains(serviceType))
645 return true;
648 if (serviceType.IsGenericType && NamingSubSystem.Contains(serviceType.GetGenericTypeDefinition()))
650 return true;
653 if (Parent != null)
655 return Parent.HasComponent(serviceType);
658 return false;
661 public virtual object this[String key]
665 if (key == null) throw new ArgumentNullException("key");
667 if (!HasComponent(key))
669 throw new ComponentNotFoundException(key);
672 IHandler handler = GetHandler(key);
674 return ResolveComponent(handler);
678 public virtual object this[Type service]
682 if (service == null) throw new ArgumentNullException("service");
684 if (!HasComponent(service))
686 throw new ComponentNotFoundException(service);
689 IHandler handler = GetHandler(service);
691 return ResolveComponent(handler, service);
695 /// <summary>
696 /// Returns the component instance by the service type
697 /// </summary>
698 public object Resolve(Type service)
700 if (service == null) throw new ArgumentNullException("service");
702 return this[service];
705 /// <summary>
706 /// Returns the component instance by the service type
707 /// using dynamic arguments
708 /// </summary>
709 /// <param name="service"></param>
710 /// <param name="arguments"></param>
711 /// <returns></returns>
712 public object Resolve(Type service, IDictionary arguments)
714 if (service == null) throw new ArgumentNullException("service");
715 if (arguments == null) throw new ArgumentNullException("arguments");
717 if (!HasComponent(service))
719 throw new ComponentNotFoundException(service);
722 IHandler handler = GetHandler(service);
724 return ResolveComponent(handler, service, arguments);
727 /// <summary>
728 /// Returns the component instance by the component key
729 /// using dynamic arguments
730 /// </summary>
731 /// <param name="key"></param>
732 /// <param name="arguments"></param>
733 /// <returns></returns>
734 public object Resolve(string key, IDictionary arguments)
736 if (key == null) throw new ArgumentNullException("key");
737 if (arguments == null) throw new ArgumentNullException("arguments");
739 if (!HasComponent(key))
741 throw new ComponentNotFoundException(key);
744 IHandler handler = GetHandler(key);
746 return ResolveComponent(handler, arguments);
750 public void RegisterCustomDependencies(Type service, IDictionary dependencies)
752 IHandler handler = GetHandler(service);
754 foreach(DictionaryEntry entry in dependencies)
756 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
760 public void RegisterCustomDependencies(String key, IDictionary dependencies)
762 IHandler handler = GetHandler(key);
764 foreach(DictionaryEntry entry in dependencies)
766 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
770 /// <summary>
771 /// Returns a component instance by the key
772 /// </summary>
773 /// <param name="key"></param>
774 /// <param name="service"></param>
775 /// <returns></returns>
776 public virtual object Resolve(String key, Type service)
778 if (key == null) throw new ArgumentNullException("key");
779 if (service == null) throw new ArgumentNullException("service");
781 if (!HasComponent(key))
783 throw new ComponentNotFoundException(key);
786 IHandler handler = GetHandler(key);
788 return ResolveComponent(handler, service);
792 public TService[] ResolveServices<TService>()
794 List<TService> services = new List<TService>();
795 IHandler[] handlers = GetHandlers(typeof(TService));
797 foreach(IHandler handler in handlers)
799 if (handler.CurrentState == HandlerState.Valid)
801 services.Add((TService) ResolveComponent(handler));
805 return services.ToArray();
808 /// <summary>
809 /// Returns a component instance by the key
810 /// </summary>
811 /// <param name="key"></param>
812 /// <param name="service"></param>
813 /// <param name="arguments"></param>
814 /// <returns></returns>
815 public virtual object Resolve(String key, Type service, IDictionary arguments)
817 if (key == null) throw new ArgumentNullException("key");
818 if (service == null) throw new ArgumentNullException("service");
820 if (!HasComponent(key))
822 throw new ComponentNotFoundException(key);
825 IHandler handler = GetHandler(key);
827 return ResolveComponent(handler, service, arguments);
830 public virtual void ReleaseComponent(object instance)
832 if (ReleasePolicy.HasTrack(instance))
834 ReleasePolicy.Release(instance);
836 else
838 if (Parent != null)
840 Parent.ReleaseComponent(instance);
845 public IHandlerFactory HandlerFactory
847 get { return handlerFactory; }
850 public IComponentModelBuilder ComponentModelBuilder
852 get { return modelBuilder; }
853 set { modelBuilder = value; }
856 public IProxyFactory ProxyFactory
858 get { return proxyFactory; }
859 set { proxyFactory = value; }
862 public virtual IConfigurationStore ConfigurationStore
864 get { return GetSubSystem(SubSystemConstants.ConfigurationStoreKey) as IConfigurationStore; }
865 set { AddSubSystem(SubSystemConstants.ConfigurationStoreKey, value); }
868 public virtual IHandler GetHandler(String key)
870 if (key == null) throw new ArgumentNullException("key");
872 IHandler handler = NamingSubSystem.GetHandler(key);
874 if (handler == null && Parent != null)
876 handler = WrapParentHandler(Parent.GetHandler(key));
879 return handler;
882 public virtual IHandler GetHandler(Type service)
884 if (service == null) throw new ArgumentNullException("service");
886 IHandler handler = NamingSubSystem.GetHandler(service);
888 if (handler == null && service.IsGenericType)
890 handler = NamingSubSystem.GetHandler(service.GetGenericTypeDefinition());
893 if (handler == null && Parent != null)
895 handler = WrapParentHandler(Parent.GetHandler(service));
898 return handler;
901 /// <summary>
902 /// Return handlers for components that
903 /// implements the specified service.
904 /// </summary>
905 /// <param name="service"></param>
906 /// <returns></returns>
907 public virtual IHandler[] GetHandlers(Type service)
909 IHandler[] result = NamingSubSystem.GetHandlers(service);
911 // a complete generic type, Foo<Bar>, need to check if Foo<T> is registered
912 if (service.IsGenericType && !service.IsGenericTypeDefinition)
914 IHandler[] genericResult = NamingSubSystem.GetHandlers(service.GetGenericTypeDefinition());
916 if (result.Length == 0)
918 result = genericResult;
920 else
922 IHandler[] mergedResult = new IHandler[result.Length + genericResult.Length];
923 result.CopyTo(mergedResult, 0);
924 genericResult.CopyTo(mergedResult, result.Length);
925 result = mergedResult;
929 // If a parent kernel exists, we merge both results
930 if (Parent != null)
932 IHandler[] parentResult = Parent.GetHandlers(service);
934 if (parentResult.Length != 0)
936 IHandler[] newResult = new IHandler[result.Length + parentResult.Length];
938 Array.Copy(result, newResult, result.Length);
939 Array.Copy(parentResult, 0, newResult, result.Length, parentResult.Length);
941 result = newResult;
945 return result;
948 /// <summary>
949 /// Return handlers for components that
950 /// implements the specified service.
951 /// The check is made using IsAssignableFrom
952 /// </summary>
953 /// <param name="service"></param>
954 /// <returns></returns>
955 public virtual IHandler[] GetAssignableHandlers(Type service)
957 return NamingSubSystem.GetAssignableHandlers(service);
960 public virtual IReleasePolicy ReleasePolicy
962 get { return releaserPolicy; }
963 set { releaserPolicy = value; }
966 public virtual void AddFacility(String key, IFacility facility)
968 if (key == null) throw new ArgumentNullException("key");
969 if (facility == null) throw new ArgumentNullException("facility");
971 facility.Init(this, ConfigurationStore.GetFacilityConfiguration(key));
973 facilities.Add(facility);
976 /// <summary>
977 /// Returns the facilities registered on the kernel.
978 /// </summary>
979 /// <returns></returns>
980 public virtual IFacility[] GetFacilities()
982 IFacility[] list = new IFacility[facilities.Count];
983 facilities.CopyTo(list, 0);
984 return list;
987 public virtual void AddSubSystem(String key, ISubSystem subsystem)
989 if (key == null) throw new ArgumentNullException("key");
990 if (subsystem == null) throw new ArgumentNullException("facility");
992 subsystem.Init(this);
993 subsystems[key] = subsystem;
996 public virtual ISubSystem GetSubSystem(String key)
998 if (key == null) throw new ArgumentNullException("key");
1000 return subsystems[key] as ISubSystem;
1003 public virtual void AddChildKernel(IKernel childKernel)
1005 if (childKernel == null) throw new ArgumentNullException("childKernel");
1007 childKernel.Parent = this;
1008 childKernels.Add(childKernel);
1011 public virtual IKernel Parent
1013 get { return parentKernel; }
1016 // TODO: should the raise add/removed as child kernel methods be invoked from within the subscriber/unsubscribe methods?
1018 if (value == null)
1020 if (parentKernel != null)
1022 UnsubscribeFromParentKernel();
1023 RaiseRemovedAsChildKernel();
1026 parentKernel = null;
1028 else
1030 if ((parentKernel != value) && (parentKernel != null))
1032 throw new KernelException(
1033 "You can not change the kernel parent once set, use the RemoveChildKernel and AddChildKernel methods together to achieve this.");
1035 parentKernel = value;
1036 SubscribeToParentKernel();
1037 RaiseAddedAsChildKernel();
1042 public IDependencyResolver Resolver
1044 get { return resolver; }
1047 public virtual IComponentActivator CreateComponentActivator(ComponentModel model)
1049 if (model == null) throw new ArgumentNullException("model");
1051 IComponentActivator activator;
1053 if (model.CustomComponentActivator == null)
1055 activator = new DefaultComponentActivator(model, this,
1056 new ComponentInstanceDelegate(RaiseComponentCreated),
1057 new ComponentInstanceDelegate(RaiseComponentDestroyed));
1059 else
1063 activator = (IComponentActivator)
1064 Activator.CreateInstance(model.CustomComponentActivator,
1065 new object[]
1067 model,
1068 this,
1069 new ComponentInstanceDelegate(RaiseComponentCreated),
1070 new ComponentInstanceDelegate(RaiseComponentDestroyed)
1073 catch(Exception e)
1075 throw new KernelException("Could not instantiate custom activator", e);
1079 return activator;
1082 /// <summary>
1083 /// Graph of components and iteractions.
1084 /// </summary>
1085 public GraphNode[] GraphNodes
1089 GraphNode[] nodes = new GraphNode[NamingSubSystem.ComponentCount];
1091 int index = 0;
1093 IHandler[] handlers = NamingSubSystem.GetHandlers();
1095 foreach(IHandler handler in handlers)
1097 nodes[index++] = handler.ComponentModel;
1100 return nodes;
1104 public virtual void RemoveChildKernel(IKernel childKernel)
1106 if (childKernel == null) throw new ArgumentNullException("childKernel");
1107 childKernel.Parent = null;
1108 childKernels.Remove(childKernel);
1111 #endregion
1113 #region IServiceProviderEx Members
1115 /// <summary>
1116 /// Gets the service object of the specified type.
1117 /// </summary>
1119 /// <returns>
1120 /// A service object of type serviceType.
1121 /// </returns>
1123 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
1124 public object GetService(Type serviceType)
1126 return Resolve(serviceType);
1129 /// <summary>
1130 /// Gets the service object of the specified type.
1131 /// </summary>
1133 /// <returns>
1134 /// A service object of type serviceType.
1135 /// </returns>
1136 public T GetService<T>()
1138 Type serviceType = typeof(T);
1139 return (T) Resolve(serviceType);
1142 #endregion
1144 #region IDisposable Members
1146 /// <summary>
1147 /// Starts the process of component disposal.
1148 /// </summary>
1149 public virtual void Dispose()
1151 DisposeSubKernels();
1152 TerminateFacilities();
1153 DisposeComponentsInstancesWithinTracker();
1154 DisposeHandlers();
1155 UnsubscribeFromParentKernel();
1158 private void TerminateFacilities()
1160 foreach(IFacility facility in facilities)
1162 facility.Terminate();
1166 private void DisposeHandlers()
1168 GraphNode[] nodes = GraphNodes;
1169 IVertex[] vertices = TopologicalSortAlgo.Sort(nodes);
1171 for(int i = 0; i < vertices.Length; i++)
1173 ComponentModel model = (ComponentModel) vertices[i];
1175 // Prevent the removal of a component that belongs
1176 // to other container
1177 if (!NamingSubSystem.Contains(model.Name)) continue;
1179 RemoveComponent(model.Name);
1183 private void UnsubscribeFromParentKernel()
1185 if (parentKernel != null)
1187 parentKernel.HandlerRegistered -= new HandlerDelegate(HandlerRegisteredOnParentKernel);
1188 parentKernel.ComponentRegistered -= new ComponentDataDelegate(RaiseComponentRegistered);
1189 parentKernel.ComponentUnregistered -= new ComponentDataDelegate(RaiseComponentUnregistered);
1193 private void SubscribeToParentKernel()
1195 if (parentKernel != null)
1197 parentKernel.HandlerRegistered += new HandlerDelegate(HandlerRegisteredOnParentKernel);
1198 parentKernel.ComponentRegistered += new ComponentDataDelegate(RaiseComponentRegistered);
1199 parentKernel.ComponentUnregistered += new ComponentDataDelegate(RaiseComponentUnregistered);
1203 private void HandlerRegisteredOnParentKernel(IHandler handler, ref bool stateChanged)
1205 RaiseHandlerRegistered(handler);
1208 private void DisposeComponentsInstancesWithinTracker()
1210 ReleasePolicy.Dispose();
1213 private void DisposeSubKernels()
1215 foreach(IKernel childKernel in childKernels)
1217 childKernel.Dispose();
1221 protected void DisposeHandler(IHandler handler)
1223 if (handler == null) return;
1225 if (handler is IDisposable)
1227 ((IDisposable) handler).Dispose();
1231 #endregion
1233 #region Protected members
1235 protected virtual IHandler WrapParentHandler(IHandler parentHandler)
1237 if (parentHandler == null) return null;
1239 // This has a very destructive side-effect. While the goal is to resolve on same-level containers,
1240 // the resolver will invoke GetHandler recursively, leading to stack overflows
1241 // return new ParentHandlerWithChildResolver(parentHandler, Resolver);
1242 return parentHandler;
1245 protected INamingSubSystem NamingSubSystem
1247 get { return GetSubSystem(SubSystemConstants.NamingKey) as INamingSubSystem; }
1250 protected void RegisterHandler(String key, IHandler handler)
1252 RegisterHandler(key, handler, false);
1255 protected void RegisterHandler(String key, IHandler handler, bool skipRegistration)
1257 if (!skipRegistration)
1259 NamingSubSystem.Register(key, handler);
1262 base.RaiseHandlerRegistered(handler);
1263 base.RaiseComponentRegistered(key, handler);
1266 protected object ResolveComponent(IHandler handler)
1268 return ResolveComponent(handler, handler.ComponentModel.Service);
1271 protected object ResolveComponent(IHandler handler, Type service)
1273 return ResolveComponent(handler, service, null);
1276 protected object ResolveComponent(IHandler handler, IDictionary additionalArguments)
1278 return ResolveComponent(handler, handler.ComponentModel.Service, additionalArguments);
1281 protected object ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments)
1283 CreationContext context = CreateCreationContext(handler, service, additionalArguments);
1285 object instance = handler.Resolve(context);
1287 ReleasePolicy.Track(instance, handler);
1289 return instance;
1292 protected CreationContext CreateCreationContext(IHandler handler, Type typeToExtractGenericArguments,
1293 IDictionary additionalArguments)
1295 return new CreationContext(handler, typeToExtractGenericArguments, additionalArguments);
1298 #endregion
1300 #region Serialization and Deserialization
1302 public override void GetObjectData(SerializationInfo info, StreamingContext context)
1304 base.GetObjectData(info, context);
1306 MemberInfo[] members = FormatterServices.GetSerializableMembers(GetType(), context);
1308 object[] kernelmembers = FormatterServices.GetObjectData(this, members);
1310 info.AddValue("members", kernelmembers, typeof(object[]));
1313 void IDeserializationCallback.OnDeserialization(object sender)
1317 #endregion