Added bidirectional support for DictionaryStringListAttribute.cs so you can assign...
[castle.git] / InversionOfControl / Castle.MicroKernel / DefaultKernel.cs
blob286d9d7d23a813e7c0f755ec781b26c32d157c43
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 IHandler[] mergedResult = new IHandler[result.Length + genericResult.Length];
919 result.CopyTo(mergedResult, 0);
920 genericResult.CopyTo(mergedResult, result.Length);
921 result = mergedResult;
923 else
925 result = genericResult;
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];
937 result.CopyTo(newResult, 0);
938 parentResult.CopyTo(newResult, result.Length);
939 result = newResult;
943 return result;
946 /// <summary>
947 /// Return handlers for components that
948 /// implements the specified service.
949 /// The check is made using IsAssignableFrom
950 /// </summary>
951 /// <param name="service"></param>
952 /// <returns></returns>
953 public virtual IHandler[] GetAssignableHandlers(Type service)
955 return NamingSubSystem.GetAssignableHandlers(service);
958 public virtual IReleasePolicy ReleasePolicy
960 get { return releaserPolicy; }
961 set { releaserPolicy = value; }
964 public virtual void AddFacility(String key, IFacility facility)
966 if (key == null) throw new ArgumentNullException("key");
967 if (facility == null) throw new ArgumentNullException("facility");
969 facility.Init(this, ConfigurationStore.GetFacilityConfiguration(key));
971 facilities.Add(facility);
974 /// <summary>
975 /// Returns the facilities registered on the kernel.
976 /// </summary>
977 /// <returns></returns>
978 public virtual IFacility[] GetFacilities()
980 IFacility[] list = new IFacility[facilities.Count];
981 facilities.CopyTo(list, 0);
982 return list;
985 public virtual void AddSubSystem(String key, ISubSystem subsystem)
987 if (key == null) throw new ArgumentNullException("key");
988 if (subsystem == null) throw new ArgumentNullException("facility");
990 subsystem.Init(this);
991 subsystems[key] = subsystem;
994 public virtual ISubSystem GetSubSystem(String key)
996 if (key == null) throw new ArgumentNullException("key");
998 return subsystems[key] as ISubSystem;
1001 public virtual void AddChildKernel(IKernel childKernel)
1003 if (childKernel == null) throw new ArgumentNullException("childKernel");
1005 childKernel.Parent = this;
1006 childKernels.Add(childKernel);
1009 public virtual IKernel Parent
1011 get { return parentKernel; }
1014 // TODO: should the raise add/removed as child kernel methods be invoked from within the subscriber/unsubscribe methods?
1016 if (value == null)
1018 if (parentKernel != null)
1020 UnsubscribeFromParentKernel();
1021 RaiseRemovedAsChildKernel();
1024 parentKernel = null;
1026 else
1028 if ((parentKernel != value) && (parentKernel != null))
1030 throw new KernelException(
1031 "You can not change the kernel parent once set, use the RemoveChildKernel and AddChildKernel methods together to achieve this.");
1033 parentKernel = value;
1034 SubscribeToParentKernel();
1035 RaiseAddedAsChildKernel();
1040 public IDependencyResolver Resolver
1042 get { return resolver; }
1045 public virtual IComponentActivator CreateComponentActivator(ComponentModel model)
1047 if (model == null) throw new ArgumentNullException("model");
1049 IComponentActivator activator;
1051 if (model.CustomComponentActivator == null)
1053 activator = new DefaultComponentActivator(model, this,
1054 new ComponentInstanceDelegate(RaiseComponentCreated),
1055 new ComponentInstanceDelegate(RaiseComponentDestroyed));
1057 else
1061 activator = (IComponentActivator)
1062 Activator.CreateInstance(model.CustomComponentActivator,
1063 new object[]
1065 model,
1066 this,
1067 new ComponentInstanceDelegate(RaiseComponentCreated),
1068 new ComponentInstanceDelegate(RaiseComponentDestroyed)
1071 catch(Exception e)
1073 throw new KernelException("Could not instantiate custom activator", e);
1077 return activator;
1080 /// <summary>
1081 /// Graph of components and iteractions.
1082 /// </summary>
1083 public GraphNode[] GraphNodes
1087 GraphNode[] nodes = new GraphNode[NamingSubSystem.ComponentCount];
1089 int index = 0;
1091 IHandler[] handlers = NamingSubSystem.GetHandlers();
1093 foreach(IHandler handler in handlers)
1095 nodes[index++] = handler.ComponentModel;
1098 return nodes;
1102 public virtual void RemoveChildKernel(IKernel childKernel)
1104 if (childKernel == null) throw new ArgumentNullException("childKernel");
1105 childKernel.Parent = null;
1106 childKernels.Remove(childKernel);
1109 #endregion
1111 #region IServiceProviderEx Members
1113 /// <summary>
1114 /// Gets the service object of the specified type.
1115 /// </summary>
1117 /// <returns>
1118 /// A service object of type serviceType.
1119 /// </returns>
1121 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
1122 public object GetService(Type serviceType)
1124 return Resolve(serviceType);
1127 /// <summary>
1128 /// Gets the service object of the specified type.
1129 /// </summary>
1131 /// <returns>
1132 /// A service object of type serviceType.
1133 /// </returns>
1134 public T GetService<T>()
1136 Type serviceType = typeof(T);
1137 return (T) Resolve(serviceType);
1140 #endregion
1142 #region IDisposable Members
1144 /// <summary>
1145 /// Starts the process of component disposal.
1146 /// </summary>
1147 public virtual void Dispose()
1149 DisposeSubKernels();
1150 TerminateFacilities();
1151 DisposeComponentsInstancesWithinTracker();
1152 DisposeHandlers();
1153 UnsubscribeFromParentKernel();
1156 private void TerminateFacilities()
1158 foreach(IFacility facility in facilities)
1160 facility.Terminate();
1164 private void DisposeHandlers()
1166 GraphNode[] nodes = GraphNodes;
1167 IVertex[] vertices = TopologicalSortAlgo.Sort(nodes);
1169 for(int i = 0; i < vertices.Length; i++)
1171 ComponentModel model = (ComponentModel) vertices[i];
1173 // Prevent the removal of a component that belongs
1174 // to other container
1175 if (!NamingSubSystem.Contains(model.Name)) continue;
1177 RemoveComponent(model.Name);
1181 private void UnsubscribeFromParentKernel()
1183 if (parentKernel != null)
1185 parentKernel.HandlerRegistered -= new HandlerDelegate(HandlerRegisteredOnParentKernel);
1186 parentKernel.ComponentRegistered -= new ComponentDataDelegate(RaiseComponentRegistered);
1187 parentKernel.ComponentUnregistered -= new ComponentDataDelegate(RaiseComponentUnregistered);
1191 private void SubscribeToParentKernel()
1193 if (parentKernel != null)
1195 parentKernel.HandlerRegistered += new HandlerDelegate(HandlerRegisteredOnParentKernel);
1196 parentKernel.ComponentRegistered += new ComponentDataDelegate(RaiseComponentRegistered);
1197 parentKernel.ComponentUnregistered += new ComponentDataDelegate(RaiseComponentUnregistered);
1201 private void HandlerRegisteredOnParentKernel(IHandler handler, ref bool stateChanged)
1203 RaiseHandlerRegistered(handler);
1206 private void DisposeComponentsInstancesWithinTracker()
1208 ReleasePolicy.Dispose();
1211 private void DisposeSubKernels()
1213 foreach(IKernel childKernel in childKernels)
1215 childKernel.Dispose();
1219 protected void DisposeHandler(IHandler handler)
1221 if (handler == null) return;
1223 if (handler is IDisposable)
1225 ((IDisposable) handler).Dispose();
1229 #endregion
1231 #region Protected members
1233 protected virtual IHandler WrapParentHandler(IHandler parentHandler)
1235 if (parentHandler == null) return null;
1237 // This has a very destructive side-effect. While the goal is to resolve on same-level containers,
1238 // the resolver will invoke GetHandler recursively, leading to stack overflows
1239 // return new ParentHandlerWithChildResolver(parentHandler, Resolver);
1240 return parentHandler;
1243 protected INamingSubSystem NamingSubSystem
1245 get { return GetSubSystem(SubSystemConstants.NamingKey) as INamingSubSystem; }
1248 protected void RegisterHandler(String key, IHandler handler)
1250 RegisterHandler(key, handler, false);
1253 protected void RegisterHandler(String key, IHandler handler, bool skipRegistration)
1255 if (!skipRegistration)
1257 NamingSubSystem.Register(key, handler);
1260 base.RaiseHandlerRegistered(handler);
1261 base.RaiseComponentRegistered(key, handler);
1264 protected object ResolveComponent(IHandler handler)
1266 return ResolveComponent(handler, handler.ComponentModel.Service);
1269 protected object ResolveComponent(IHandler handler, Type service)
1271 return ResolveComponent(handler, service, null);
1274 protected object ResolveComponent(IHandler handler, IDictionary additionalArguments)
1276 return ResolveComponent(handler, handler.ComponentModel.Service, additionalArguments);
1279 protected object ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments)
1281 CreationContext context = CreateCreationContext(handler, service, additionalArguments);
1283 object instance = handler.Resolve(context);
1285 ReleasePolicy.Track(instance, handler);
1287 return instance;
1290 protected CreationContext CreateCreationContext(IHandler handler, Type typeToExtractGenericArguments,
1291 IDictionary additionalArguments)
1293 return new CreationContext(handler, typeToExtractGenericArguments, additionalArguments);
1296 #endregion
1298 #region Serialization and Deserialization
1300 public override void GetObjectData(SerializationInfo info, StreamingContext context)
1302 base.GetObjectData(info, context);
1304 MemberInfo[] members = FormatterServices.GetSerializableMembers(GetType(), context);
1306 object[] kernelmembers = FormatterServices.GetObjectData(this, members);
1308 info.AddValue("members", kernelmembers, typeof(object[]));
1311 void IDeserializationCallback.OnDeserialization(object sender)
1315 #endregion