Allow component registration specification of LifeStyle using LifeStyleType.
[castle.git] / InversionOfControl / Castle.MicroKernel / DefaultKernel.cs
blobdd120bc46e6399f277b8474163e95d284dc1e9ac
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 /// Registers the components described by the <see cref="ComponentRegistration{S}"/>s
550 /// with the <see cref="IKernel"/>.
551 /// <param name="registrations">The component registrations.</param>
552 /// <returns>The kernel.</returns>
553 /// </summary>
554 public IKernel Register(params IRegistration[] registrations)
556 if (registrations == null)
558 throw new ArgumentNullException("registrations");
561 foreach(IRegistration registration in registrations)
563 registration.Register(this);
566 return this;
569 /// <summary>
570 /// Returns the component instance by the service type
571 /// using dynamic arguments
572 /// </summary>
573 /// <param name="arguments"></param>
574 /// <returns></returns>
575 public T Resolve<T>(IDictionary arguments)
577 Type serviceType = typeof(T);
578 return (T)Resolve(serviceType, arguments);
581 /// <summary>
582 /// Returns the component instance by the service type
583 /// using dynamic arguments
584 /// </summary>
585 /// <param name="argumentsAsAnonymousType"></param>
586 /// <returns></returns>
587 public T Resolve<T>(object argumentsAsAnonymousType)
589 return Resolve<T>(new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
592 /// <summary>
593 /// Returns the component instance by the component key
594 /// </summary>
595 /// <returns></returns>
596 public T Resolve<T>()
598 Type serviceType = typeof(T);
599 return (T)Resolve(serviceType);
602 /// <summary>
603 /// Returns true if the specified component was
604 /// found and could be removed (i.e. no other component depends on it)
605 /// </summary>
606 /// <param name="key">The component's key</param>
607 /// <returns></returns>
608 public virtual bool RemoveComponent(String key)
610 if (key == null) throw new ArgumentNullException("key");
612 if (NamingSubSystem.Contains(key))
614 IHandler handler = GetHandler(key);
616 if (handler.ComponentModel.Dependers.Length == 0)
618 NamingSubSystem.UnRegister(key);
620 IHandler[] assignableHandlers = GetAssignableHandlers(handler.ComponentModel.Service);
621 if (assignableHandlers.Length > 0)
623 NamingSubSystem[handler.ComponentModel.Service] = assignableHandlers[0];
625 else
627 NamingSubSystem.UnRegister(handler.ComponentModel.Service);
630 foreach (ComponentModel model in handler.ComponentModel.Dependents)
632 model.RemoveDepender(handler.ComponentModel);
635 RaiseComponentUnregistered(key, handler);
637 DisposeHandler(handler);
639 return true;
641 else
643 // We can't remove this component as there are
644 // others which depends on it
646 return false;
650 if (Parent != null)
652 return Parent.RemoveComponent(key);
655 return false;
658 public virtual bool HasComponent(String key)
660 if (key == null) throw new ArgumentNullException("key");
662 if (NamingSubSystem.Contains(key))
664 return true;
667 if (Parent != null)
669 return Parent.HasComponent(key);
672 return false;
675 public virtual bool HasComponent(Type serviceType)
677 if (serviceType == null) throw new ArgumentNullException("serviceType");
679 if (NamingSubSystem.Contains(serviceType))
681 return true;
684 if (serviceType.IsGenericType && NamingSubSystem.Contains(serviceType.GetGenericTypeDefinition()))
686 return true;
689 if (Parent != null)
691 return Parent.HasComponent(serviceType);
694 return false;
697 public virtual object this[String key]
701 if (key == null) throw new ArgumentNullException("key");
703 if (!HasComponent(key))
705 throw new ComponentNotFoundException(key);
708 IHandler handler = GetHandler(key);
710 return ResolveComponent(handler);
714 public virtual object this[Type service]
718 if (service == null) throw new ArgumentNullException("service");
720 if (!HasComponent(service))
722 throw new ComponentNotFoundException(service);
725 IHandler handler = GetHandler(service);
727 return ResolveComponent(handler, service);
731 /// <summary>
732 /// Returns the component instance by the service type
733 /// </summary>
734 public object Resolve(Type service)
736 if (service == null) throw new ArgumentNullException("service");
738 return this[service];
741 /// <summary>
742 /// Returns all the valid component instances by
743 /// the service type
744 /// </summary>
745 /// <param name="service">The service type</param>
746 /// <param name="arguments">Arguments to resolve the services</param>
747 public Array ResolveAll(Type service, IDictionary arguments)
749 ArrayList list = new ArrayList();
750 IHandler[] handlers = GetAssignableHandlers(service);
751 foreach (IHandler handler in handlers)
753 if(handler.CurrentState!=HandlerState.Valid)
754 continue;
756 object component = ResolveComponent(handler, service, arguments);
757 list.Add(component);
759 return list.ToArray(service);
762 /// <summary>
763 /// Returns all the valid component instances by
764 /// the service type
765 /// </summary>
766 /// <param name="service">The service type</param>
767 /// <param name="argumentsAsAnonymousType">Arguments to resolve the services</param>
768 public Array ResolveAll(Type service, object argumentsAsAnonymousType)
770 return ResolveAll(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
774 /// <summary>
775 /// Returns component instances that implement TService
776 /// </summary>
777 /// <typeparam name="TService"></typeparam>
778 /// <param name="argumentsAsAnonymousType"></param>
779 /// <returns></returns>
780 public TService[] ResolveAll<TService>(object argumentsAsAnonymousType)
782 return (TService[]) ResolveAll(typeof(TService), argumentsAsAnonymousType);
785 /// <summary>
786 /// Returns component instances that implement TService
787 /// </summary>
788 /// <typeparam name="TService"></typeparam>
789 /// <param name="arguments"></param>
790 /// <returns></returns>
791 public TService[] ResolveAll<TService>(IDictionary arguments)
793 return (TService[])ResolveAll(typeof(TService), arguments);
798 /// <summary>
799 /// Returns the component instance by the service type
800 /// using dynamic arguments
801 /// </summary>
802 /// <param name="service"></param>
803 /// <param name="arguments"></param>
804 /// <returns></returns>
805 public object Resolve(Type service, IDictionary arguments)
807 if (service == null) throw new ArgumentNullException("service");
808 if (arguments == null) throw new ArgumentNullException("arguments");
810 if (!HasComponent(service))
812 throw new ComponentNotFoundException(service);
815 IHandler handler = GetHandler(service);
817 return ResolveComponent(handler, service, arguments);
820 /// <summary>
821 /// Returns the component instance by the service type
822 /// using dynamic arguments
823 /// </summary>
824 /// <param name="service"></param>
825 /// <param name="argumentsAsAnonymousType"></param>
826 /// <returns></returns>
827 public object Resolve(Type service, object argumentsAsAnonymousType)
829 return Resolve(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
832 /// <summary>
833 /// Returns the component instance by the component key
834 /// using dynamic arguments
835 /// </summary>
836 /// <param name="key"></param>
837 /// <param name="arguments"></param>
838 /// <returns></returns>
839 public object Resolve(string key, IDictionary arguments)
841 if (key == null) throw new ArgumentNullException("key");
842 if (arguments == null) throw new ArgumentNullException("arguments");
844 if (!HasComponent(key))
846 throw new ComponentNotFoundException(key);
849 IHandler handler = GetHandler(key);
851 return ResolveComponent(handler, arguments);
854 /// <summary>
855 /// Returns the component instance by the component key
856 /// using dynamic arguments
857 /// </summary>
858 /// <param name="key"></param>
859 /// <param name="argumentsAsAnonymousType"></param>
860 /// <returns></returns>
861 public object Resolve(string key, object argumentsAsAnonymousType)
863 return Resolve(key, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
866 /// <summary>
867 /// Associates objects with a component handler,
868 /// allowing it to use the specified dictionary
869 /// when resolving dependencies
870 /// </summary>
871 /// <param name="service"></param>
872 /// <param name="dependencies"></param>
873 public void RegisterCustomDependencies(Type service, IDictionary dependencies)
875 IHandler handler = GetHandler(service);
877 foreach (DictionaryEntry entry in dependencies)
879 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
883 /// <summary>
884 /// Associates objects with a component handler,
885 /// allowing it to use the specified dictionary
886 /// when resolving dependencies
887 /// </summary>
888 /// <param name="service"></param>
889 /// <param name="dependenciesAsAnonymousType"></param>
890 public void RegisterCustomDependencies(Type service, object dependenciesAsAnonymousType)
892 RegisterCustomDependencies(service, new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType));
895 /// <summary>
896 /// Associates objects with a component handler,
897 /// allowing it to use the specified dictionary
898 /// when resolving dependencies
899 /// </summary>
900 /// <param name="key"></param>
901 /// <param name="dependencies"></param>
902 public void RegisterCustomDependencies(String key, IDictionary dependencies)
904 IHandler handler = GetHandler(key);
906 foreach (DictionaryEntry entry in dependencies)
908 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
912 /// <summary>
913 /// Associates objects with a component handler,
914 /// allowing it to use the specified dictionary
915 /// when resolving dependencies
916 /// </summary>
917 /// <param name="key"></param>
918 /// <param name="dependenciesAsAnonymousType"></param>
919 public void RegisterCustomDependencies(String key, object dependenciesAsAnonymousType)
921 RegisterCustomDependencies(key, new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType));
924 /// <summary>
925 /// Returns a component instance by the key
926 /// </summary>
927 /// <param name="key"></param>
928 /// <param name="service"></param>
929 /// <returns></returns>
930 public virtual object Resolve(String key, Type service)
932 if (key == null) throw new ArgumentNullException("key");
933 if (service == null) throw new ArgumentNullException("service");
935 if (!HasComponent(key))
937 throw new ComponentNotFoundException(key);
940 IHandler handler = GetHandler(key);
942 return ResolveComponent(handler, service);
946 /// <summary>
947 /// Returns component instances that implement TService
948 /// </summary>
949 /// <typeparam name="TService"></typeparam>
950 /// <returns></returns>
951 public TService[] ResolveAll<TService>()
953 return (TService[]) ResolveAll(typeof (TService), new Hashtable());
956 /// <summary>
957 /// Returns a component instance by the key
958 /// </summary>
959 /// <param name="key"></param>
960 /// <param name="service"></param>
961 /// <param name="arguments"></param>
962 /// <returns></returns>
963 public virtual object Resolve(String key, Type service, IDictionary arguments)
965 if (key == null) throw new ArgumentNullException("key");
966 if (service == null) throw new ArgumentNullException("service");
968 if (!HasComponent(key))
970 throw new ComponentNotFoundException(key);
973 IHandler handler = GetHandler(key);
975 return ResolveComponent(handler, service, arguments);
978 /// <summary>
979 /// Resolves the specified key.
980 /// </summary>
981 /// <param name="key">The key.</param>
982 /// <param name="service">The service.</param>
983 /// <param name="argumentsAsAnonymousType">Type of the arguments as anonymous.</param>
984 /// <returns></returns>
985 public virtual object Resolve(String key, Type service, object argumentsAsAnonymousType)
987 return Resolve(key, service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
990 /// <summary>
991 /// Releases a component instance. This allows
992 /// the kernel to execute the proper decomission
993 /// lifecycles on the component instance.
994 /// </summary>
995 /// <param name="instance"></param>
996 public virtual void ReleaseComponent(object instance)
998 if (ReleasePolicy.HasTrack(instance))
1000 ReleasePolicy.Release(instance);
1002 else
1004 if (Parent != null)
1006 Parent.ReleaseComponent(instance);
1011 public IHandlerFactory HandlerFactory
1013 get { return handlerFactory; }
1016 public IComponentModelBuilder ComponentModelBuilder
1018 get { return modelBuilder; }
1019 set { modelBuilder = value; }
1022 public IProxyFactory ProxyFactory
1024 get { return proxyFactory; }
1025 set { proxyFactory = value; }
1028 public virtual IConfigurationStore ConfigurationStore
1030 get { return GetSubSystem(SubSystemConstants.ConfigurationStoreKey) as IConfigurationStore; }
1031 set { AddSubSystem(SubSystemConstants.ConfigurationStoreKey, value); }
1034 public virtual IHandler GetHandler(String key)
1036 if (key == null) throw new ArgumentNullException("key");
1038 IHandler handler = NamingSubSystem.GetHandler(key);
1040 if (handler == null && Parent != null)
1042 handler = WrapParentHandler(Parent.GetHandler(key));
1045 return handler;
1048 public virtual IHandler GetHandler(Type service)
1050 if (service == null) throw new ArgumentNullException("service");
1052 IHandler handler = NamingSubSystem.GetHandler(service);
1054 if (handler == null && service.IsGenericType)
1056 handler = NamingSubSystem.GetHandler(service.GetGenericTypeDefinition());
1059 if (handler == null && Parent != null)
1061 handler = WrapParentHandler(Parent.GetHandler(service));
1064 return handler;
1067 /// <summary>
1068 /// Return handlers for components that
1069 /// implements the specified service.
1070 /// </summary>
1071 /// <param name="service"></param>
1072 /// <returns></returns>
1073 public virtual IHandler[] GetHandlers(Type service)
1075 IHandler[] result = NamingSubSystem.GetHandlers(service);
1077 // a complete generic type, Foo<Bar>, need to check if Foo<T> is registered
1078 if (service.IsGenericType && !service.IsGenericTypeDefinition)
1080 IHandler[] genericResult = NamingSubSystem.GetHandlers(service.GetGenericTypeDefinition());
1082 if (result.Length > 0)
1084 IHandler[] mergedResult = new IHandler[result.Length + genericResult.Length];
1085 result.CopyTo(mergedResult, 0);
1086 genericResult.CopyTo(mergedResult, result.Length);
1087 result = mergedResult;
1089 else
1091 result = genericResult;
1095 // If a parent kernel exists, we merge both results
1096 if (Parent != null)
1098 IHandler[] parentResult = Parent.GetHandlers(service);
1100 if (parentResult.Length > 0)
1102 IHandler[] newResult = new IHandler[result.Length + parentResult.Length];
1103 result.CopyTo(newResult, 0);
1104 parentResult.CopyTo(newResult, result.Length);
1105 result = newResult;
1109 return result;
1112 /// <summary>
1113 /// Return handlers for components that
1114 /// implements the specified service.
1115 /// The check is made using IsAssignableFrom
1116 /// </summary>
1117 /// <param name="service"></param>
1118 /// <returns></returns>
1119 public virtual IHandler[] GetAssignableHandlers(Type service)
1121 return NamingSubSystem.GetAssignableHandlers(service);
1124 public virtual IReleasePolicy ReleasePolicy
1126 get { return releaserPolicy; }
1127 set { releaserPolicy = value; }
1130 public virtual void AddFacility(String key, IFacility facility)
1132 if (key == null) throw new ArgumentNullException("key");
1133 if (facility == null) throw new ArgumentNullException("facility");
1135 facility.Init(this, ConfigurationStore.GetFacilityConfiguration(key));
1137 facilities.Add(facility);
1140 public void AddFacility<T>(String key) where T : IFacility, new()
1142 AddFacility(key, new T());
1145 public void AddFacility<T>() where T : IFacility, new()
1147 AddFacility<T>(typeof(T).FullName);
1150 /// <summary>
1151 /// Returns the facilities registered on the kernel.
1152 /// </summary>
1153 /// <returns></returns>
1154 public virtual IFacility[] GetFacilities()
1156 IFacility[] list = new IFacility[facilities.Count];
1157 facilities.CopyTo(list, 0);
1158 return list;
1161 public virtual void AddSubSystem(String key, ISubSystem subsystem)
1163 if (key == null) throw new ArgumentNullException("key");
1164 if (subsystem == null) throw new ArgumentNullException("facility");
1166 subsystem.Init(this);
1167 subsystems[key] = subsystem;
1170 public virtual ISubSystem GetSubSystem(String key)
1172 if (key == null) throw new ArgumentNullException("key");
1174 return subsystems[key] as ISubSystem;
1177 public virtual void AddChildKernel(IKernel childKernel)
1179 if (childKernel == null) throw new ArgumentNullException("childKernel");
1181 childKernel.Parent = this;
1182 childKernels.Add(childKernel);
1185 public virtual IKernel Parent
1187 get { return parentKernel; }
1190 // TODO: should the raise add/removed as child kernel methods be invoked from within the subscriber/unsubscribe methods?
1192 if (value == null)
1194 if (parentKernel != null)
1196 UnsubscribeFromParentKernel();
1197 RaiseRemovedAsChildKernel();
1200 parentKernel = null;
1202 else
1204 if ((parentKernel != value) && (parentKernel != null))
1206 throw new KernelException(
1207 "You can not change the kernel parent once set, use the RemoveChildKernel and AddChildKernel methods together to achieve this.");
1209 parentKernel = value;
1210 SubscribeToParentKernel();
1211 RaiseAddedAsChildKernel();
1216 public IDependencyResolver Resolver
1218 get { return resolver; }
1221 public virtual IComponentActivator CreateComponentActivator(ComponentModel model)
1223 if (model == null) throw new ArgumentNullException("model");
1225 IComponentActivator activator;
1227 if (model.CustomComponentActivator == null)
1229 activator = new DefaultComponentActivator(model, this,
1230 new ComponentInstanceDelegate(RaiseComponentCreated),
1231 new ComponentInstanceDelegate(RaiseComponentDestroyed));
1233 else
1237 activator = (IComponentActivator)
1238 Activator.CreateInstance(model.CustomComponentActivator,
1239 new object[]
1241 model,
1242 this,
1243 new ComponentInstanceDelegate(RaiseComponentCreated),
1244 new ComponentInstanceDelegate(RaiseComponentDestroyed)
1247 catch (Exception e)
1249 throw new KernelException("Could not instantiate custom activator", e);
1253 return activator;
1256 /// <summary>
1257 /// Graph of components and iteractions.
1258 /// </summary>
1259 public GraphNode[] GraphNodes
1263 GraphNode[] nodes = new GraphNode[NamingSubSystem.ComponentCount];
1265 int index = 0;
1267 IHandler[] handlers = NamingSubSystem.GetHandlers();
1269 foreach (IHandler handler in handlers)
1271 nodes[index++] = handler.ComponentModel;
1274 return nodes;
1278 public virtual void RemoveChildKernel(IKernel childKernel)
1280 if (childKernel == null) throw new ArgumentNullException("childKernel");
1281 childKernel.Parent = null;
1282 childKernels.Remove(childKernel);
1285 #endregion
1287 #region IServiceProviderEx Members
1289 /// <summary>
1290 /// Gets the service object of the specified type.
1291 /// </summary>
1293 /// <returns>
1294 /// A service object of type serviceType.
1295 /// </returns>
1297 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
1298 public object GetService(Type serviceType)
1300 if (!HasComponent(serviceType))
1302 return null;
1305 return Resolve(serviceType);
1308 /// <summary>
1309 /// Gets the service object of the specified type.
1310 /// </summary>
1312 /// <returns>
1313 /// A service object of type serviceType.
1314 /// </returns>
1315 public T GetService<T>() where T : class
1317 Type serviceType = typeof(T);
1319 if (!HasComponent(serviceType))
1321 return null;
1324 return (T)Resolve(serviceType);
1327 #endregion
1329 #region IDisposable Members
1331 /// <summary>
1332 /// Starts the process of component disposal.
1333 /// </summary>
1334 public virtual void Dispose()
1336 DisposeSubKernels();
1337 TerminateFacilities();
1338 DisposeComponentsInstancesWithinTracker();
1339 DisposeHandlers();
1340 UnsubscribeFromParentKernel();
1343 private void TerminateFacilities()
1345 foreach (IFacility facility in facilities)
1347 facility.Terminate();
1351 private void DisposeHandlers()
1353 GraphNode[] nodes = GraphNodes;
1354 IVertex[] vertices = TopologicalSortAlgo.Sort(nodes);
1356 for (int i = 0; i < vertices.Length; i++)
1358 ComponentModel model = (ComponentModel)vertices[i];
1360 // Prevent the removal of a component that belongs
1361 // to other container
1362 if (!NamingSubSystem.Contains(model.Name)) continue;
1364 RemoveComponent(model.Name);
1368 private void UnsubscribeFromParentKernel()
1370 if (parentKernel != null)
1372 parentKernel.HandlerRegistered -= new HandlerDelegate(HandlerRegisteredOnParentKernel);
1373 parentKernel.ComponentRegistered -= new ComponentDataDelegate(RaiseComponentRegistered);
1374 parentKernel.ComponentUnregistered -= new ComponentDataDelegate(RaiseComponentUnregistered);
1378 private void SubscribeToParentKernel()
1380 if (parentKernel != null)
1382 parentKernel.HandlerRegistered += new HandlerDelegate(HandlerRegisteredOnParentKernel);
1383 parentKernel.ComponentRegistered += new ComponentDataDelegate(RaiseComponentRegistered);
1384 parentKernel.ComponentUnregistered += new ComponentDataDelegate(RaiseComponentUnregistered);
1388 private void HandlerRegisteredOnParentKernel(IHandler handler, ref bool stateChanged)
1390 RaiseHandlerRegistered(handler);
1393 private void DisposeComponentsInstancesWithinTracker()
1395 ReleasePolicy.Dispose();
1398 private void DisposeSubKernels()
1400 foreach (IKernel childKernel in childKernels)
1402 childKernel.Dispose();
1406 protected void DisposeHandler(IHandler handler)
1408 if (handler == null) return;
1410 if (handler is IDisposable)
1412 ((IDisposable)handler).Dispose();
1416 #endregion
1418 #region Protected members
1420 protected virtual IHandler WrapParentHandler(IHandler parentHandler)
1422 if (parentHandler == null) return null;
1424 // This has a very destructive side-effect. While the goal is to resolve on same-level containers,
1425 // the resolver will invoke GetHandler recursively, leading to stack overflows
1426 // return new ParentHandlerWithChildResolver(parentHandler, Resolver);
1427 return parentHandler;
1430 protected INamingSubSystem NamingSubSystem
1432 get { return GetSubSystem(SubSystemConstants.NamingKey) as INamingSubSystem; }
1435 protected void RegisterHandler(String key, IHandler handler)
1437 RegisterHandler(key, handler, false);
1440 protected void RegisterHandler(String key, IHandler handler, bool skipRegistration)
1442 if (!skipRegistration)
1444 NamingSubSystem.Register(key, handler);
1447 base.RaiseHandlerRegistered(handler);
1448 base.RaiseComponentRegistered(key, handler);
1451 protected object ResolveComponent(IHandler handler)
1453 return ResolveComponent(handler, handler.ComponentModel.Service);
1456 protected object ResolveComponent(IHandler handler, Type service)
1458 return ResolveComponent(handler, service, null);
1461 protected object ResolveComponent(IHandler handler, IDictionary additionalArguments)
1463 return ResolveComponent(handler, handler.ComponentModel.Service, additionalArguments);
1466 protected object ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments)
1468 CreationContext context = CreateCreationContext(handler, service, additionalArguments);
1470 object instance = handler.Resolve(context);
1472 ReleasePolicy.Track(instance, handler);
1474 return instance;
1477 protected CreationContext CreateCreationContext(IHandler handler, Type typeToExtractGenericArguments,
1478 IDictionary additionalArguments)
1480 return new CreationContext(handler, typeToExtractGenericArguments, additionalArguments);
1483 #endregion
1485 #region Serialization and Deserialization
1487 public override void GetObjectData(SerializationInfo info, StreamingContext context)
1489 base.GetObjectData(info, context);
1491 MemberInfo[] members = FormatterServices.GetSerializableMembers(GetType(), context);
1493 object[] kernelmembers = FormatterServices.GetObjectData(this, members);
1495 info.AddValue("members", kernelmembers, typeof(object[]));
1498 void IDeserializationCallback.OnDeserialization(object sender)
1502 #endregion