Initial version of MicroKernel/Windsor fluent interface for registration (IoC-99)
[castle.git] / InversionOfControl / Castle.MicroKernel / DefaultKernel.cs
blob4ebf8f2fefdd030310fa3e6abb88918572f6558e
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.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()
101 : this(new NotSupportedProxyFactory())
105 /// <summary>
106 /// Constructs a DefaultKernel with the specified
107 /// implementation of <see cref="IProxyFactory"/> and <see cref="IDependencyResolver"/>
108 /// </summary>
109 /// <param name="resolver"></param>
110 /// <param name="proxyFactory"></param>
111 public DefaultKernel(IDependencyResolver resolver, IProxyFactory proxyFactory)
112 : this(proxyFactory)
114 this.resolver = resolver;
115 this.resolver.Initialize(new DependencyDelegate(RaiseDependencyResolving));
118 /// <summary>
119 /// Constructs a DefaultKernel with the specified
120 /// implementation of <see cref="IProxyFactory"/>
121 /// </summary>
122 public DefaultKernel(IProxyFactory proxyFactory)
124 this.proxyFactory = proxyFactory;
126 childKernels = new ArrayList();
127 facilities = new ArrayList();
128 subsystems = new Hashtable();
130 RegisterSubSystems();
132 releaserPolicy = new LifecycledComponentsReleasePolicy();
133 handlerFactory = new DefaultHandlerFactory(this);
134 modelBuilder = new DefaultComponentModelBuilder(this);
135 resolver = new DefaultDependencyResolver(this);
136 resolver.Initialize(new DependencyDelegate(RaiseDependencyResolving));
139 public DefaultKernel(SerializationInfo info, StreamingContext context)
140 : base(info, context)
142 MemberInfo[] members = FormatterServices.GetSerializableMembers(GetType(), context);
144 object[] kernelmembers = (object[])info.GetValue("members", typeof(object[]));
146 FormatterServices.PopulateObjectMembers(this, members, kernelmembers);
149 #endregion
151 #region Overridables
153 protected virtual void RegisterSubSystems()
155 AddSubSystem(SubSystemConstants.ConfigurationStoreKey,
156 new DefaultConfigurationStore());
158 AddSubSystem(SubSystemConstants.ConversionManagerKey,
159 new DefaultConversionManager());
161 AddSubSystem(SubSystemConstants.NamingKey,
162 new DefaultNamingSubSystem());
164 AddSubSystem(SubSystemConstants.ResourceKey,
165 new DefaultResourceSubSystem());
168 #endregion
170 #region IKernel Members
172 public virtual void AddComponent(String key, Type classType)
174 AddComponent(key, classType, classType);
177 /// <summary>
178 /// Adds a concrete class
179 /// as a component with the specified <paramref name="lifestyle"/>.
180 /// </summary>
181 /// <param name="key">The key with which to index the component.</param>
182 /// <param name="classType">The <see cref="Type"/> of the component.</param>
183 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
184 /// <remarks>
185 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
186 /// attributes, this method will not overwrite that lifestyle. To do that, use the
187 /// <see cref="IKernel.AddComponent(string,Type,LifestyleType,bool)"/> method.
188 /// </remarks>
189 /// <exception cref="ArgumentNullException">
190 /// Thrown if <paramref name="key"/> or <paramref name="classType"/>
191 /// are <see langword="null"/>.
192 /// </exception>
193 /// <exception cref="ArgumentException">
194 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
195 /// </exception>
196 public void AddComponent(string key, Type classType, LifestyleType lifestyle)
198 AddComponent(key, classType, classType, lifestyle);
201 /// <summary>
202 /// Adds a concrete class
203 /// as a component with the specified <paramref name="lifestyle"/>.
204 /// </summary>
205 /// <param name="key">The key with which to index the component.</param>
206 /// <param name="classType">The <see cref="Type"/> of the component.</param>
207 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
208 /// <param name="overwriteLifestyle">
209 /// If <see langword="true"/>, then ignores all other configurations
210 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.
211 /// </param>
212 /// <remarks>
213 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
214 /// attributes, this method will not overwrite that lifestyle. To do that, use the
215 /// <see cref="IKernel.AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
216 /// </remarks>
217 /// <exception cref="ArgumentNullException">
218 /// Thrown if <paramref name="key"/> or <paramref name="classType"/>
219 /// are <see langword="null"/>.
220 /// </exception>
221 /// <exception cref="ArgumentException" />
222 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
223 public void AddComponent(string key, Type classType, LifestyleType lifestyle, bool overwriteLifestyle)
225 AddComponent(key, classType, classType, lifestyle, overwriteLifestyle);
228 public virtual void AddComponent(String key, Type serviceType, Type classType)
230 AddComponent(key, serviceType, classType, LifestyleType.Singleton);
233 /// <summary>
234 /// Adds a concrete class and an interface
235 /// as a component with the specified <paramref name="lifestyle"/>.
236 /// </summary>
237 /// <param name="key">The key with which to index the component.</param>
238 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
239 /// <param name="classType">The <see cref="Type"/> of the component.</param>
240 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
241 /// <remarks>
242 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
243 /// attributes, this method will not overwrite that lifestyle. To do that, use the
244 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
245 /// </remarks>
246 /// <exception cref="ArgumentNullException">
247 /// Thrown if <paramref name="key"/>, <paramref name="serviceType"/>, or <paramref name="classType"/>
248 /// are <see langword="null"/>.
249 /// </exception>
250 /// <exception cref="ArgumentException">
251 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
252 /// </exception>
253 public void AddComponent(string key, Type serviceType, Type classType, LifestyleType lifestyle)
255 AddComponent(key, serviceType, classType, lifestyle, false);
258 /// <summary>
259 /// Adds a concrete class and an interface
260 /// as a component with the specified <paramref name="lifestyle"/>.
261 /// </summary>
262 /// <param name="key">The key with which to index the component.</param>
263 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
264 /// <param name="classType">The <see cref="Type"/> of the component.</param>
265 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
266 /// <param name="overwriteLifestyle">
267 /// If <see langword="true"/>, then ignores all other configurations
268 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.
269 /// </param>
270 /// <remarks>
271 /// If you have indicated a lifestyle for the specified <paramref name="classType"/> using
272 /// attributes, this method will not overwrite that lifestyle. To do that, use the
273 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
274 /// </remarks>
275 /// <exception cref="ArgumentNullException">
276 /// Thrown if <paramref name="key"/>, <paramref name="serviceType"/>, or <paramref name="classType"/>
277 /// are <see langword="null"/>.
278 /// </exception>
279 /// <exception cref="ArgumentException">
280 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
281 /// </exception>
282 public void AddComponent(string key, Type serviceType, Type classType, LifestyleType lifestyle,
283 bool overwriteLifestyle)
285 if (key == null) throw new ArgumentNullException("key");
286 if (serviceType == null) throw new ArgumentNullException("serviceType");
287 if (classType == null) throw new ArgumentNullException("classType");
288 if (LifestyleType.Undefined == lifestyle)
289 throw new ArgumentException("The specified lifestyle must be Thread, Transient, or Singleton.", "lifestyle");
291 ComponentModel model = ComponentModelBuilder.BuildModel(key, serviceType, classType, null);
293 if (overwriteLifestyle || LifestyleType.Undefined == model.LifestyleType)
295 model.LifestyleType = lifestyle;
298 RaiseComponentModelCreated(model);
300 IHandler handler = HandlerFactory.Create(model);
301 RegisterHandler(key, handler);
304 /// <summary>
305 ///
306 /// </summary>
307 /// <param name="key"></param>
308 /// <param name="classType"></param>
309 /// <param name="parameters"></param>
310 public virtual void AddComponentWithExtendedProperties(String key, Type classType, IDictionary parameters)
312 if (key == null) throw new ArgumentNullException("key");
313 if (parameters == null) throw new ArgumentNullException("parameters");
314 if (classType == null) throw new ArgumentNullException("classType");
316 ComponentModel model = ComponentModelBuilder.BuildModel(key, classType, classType, parameters);
317 RaiseComponentModelCreated(model);
318 IHandler handler = HandlerFactory.Create(model);
319 RegisterHandler(key, handler);
322 /// <summary>
323 ///
324 /// </summary>
325 /// <param name="key"></param>
326 /// <param name="serviceType"></param>
327 /// <param name="classType"></param>
328 /// <param name="parameters"></param>
329 public virtual void AddComponentWithExtendedProperties(String key, Type serviceType, Type classType,
330 IDictionary parameters)
332 if (key == null) throw new ArgumentNullException("key");
333 if (parameters == null) throw new ArgumentNullException("parameters");
334 if (serviceType == null) throw new ArgumentNullException("serviceType");
335 if (classType == null) throw new ArgumentNullException("classType");
337 ComponentModel model = ComponentModelBuilder.BuildModel(key, serviceType, classType, parameters);
338 RaiseComponentModelCreated(model);
339 IHandler handler = HandlerFactory.Create(model);
340 RegisterHandler(key, handler);
343 /// <summary>
344 ///
345 /// </summary>
346 /// <param name="model"></param>
347 public virtual void AddCustomComponent(ComponentModel model)
349 if (model == null) throw new ArgumentNullException("model");
351 RaiseComponentModelCreated(model);
352 IHandler handler = HandlerFactory.Create(model);
354 object skipRegistration = model.ExtendedProperties[ComponentModel.SkipRegistration];
356 if (skipRegistration != null)
358 RegisterHandler(model.Name, handler, (bool)skipRegistration);
360 else
362 RegisterHandler(model.Name, handler);
366 /// <summary>
367 /// Used mostly by facilities. Adds an instance
368 /// to be used as a component.
369 /// </summary>
370 /// <param name="key"></param>
371 /// <param name="instance"></param>
372 public void AddComponentInstance(String key, object instance)
374 if (key == null) throw new ArgumentNullException("key");
375 if (instance == null) throw new ArgumentNullException("instance");
377 Type classType = instance.GetType();
379 ComponentModel model = new ComponentModel(key, classType, classType);
380 model.CustomComponentActivator = typeof(ExternalInstanceActivator);
381 model.ExtendedProperties["instance"] = instance;
383 RaiseComponentModelCreated(model);
384 IHandler handler = HandlerFactory.Create(model);
385 RegisterHandler(key, handler);
388 /// <summary>
389 /// Used mostly by facilities. Adds an instance
390 /// to be used as a component.
391 /// </summary>
392 /// <param name="key"></param>
393 /// <param name="serviceType"></param>
394 /// <param name="instance"></param>
395 public void AddComponentInstance(String key, Type serviceType, object instance)
397 AddComponentInstance(key, serviceType, instance.GetType(), instance);
400 public void AddComponentInstance(string key, Type serviceType, Type classType, object instance)
402 if (key == null) throw new ArgumentNullException("key");
403 if (serviceType == null) throw new ArgumentNullException("serviceType");
404 if (instance == null) throw new ArgumentNullException("instance");
405 if (classType == null) throw new ArgumentNullException("classType");
407 ComponentModel model = new ComponentModel(key, serviceType, classType);
408 model.CustomComponentActivator = typeof(ExternalInstanceActivator);
409 model.ExtendedProperties["instance"] = instance;
411 RaiseComponentModelCreated(model);
412 IHandler handler = HandlerFactory.Create(model);
413 RegisterHandler(key, handler);
416 /// <summary>
417 /// Adds a concrete class as a component
418 /// </summary>
419 public void AddComponent<T>()
421 Type classType = typeof(T);
422 AddComponent(classType.FullName, classType);
425 /// <summary>
426 /// Adds a concrete class
427 /// as a component with the specified <paramref name="lifestyle"/>.
428 /// </summary>
429 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
430 /// <remarks>
431 /// If you have indicated a lifestyle for the specified T using
432 /// attributes, this method will not overwrite that lifestyle. To do that, use the
433 /// <see cref="AddComponent(string,Type,LifestyleType,bool)"/> method.
434 /// </remarks>
435 /// <exception cref="ArgumentException">
436 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
437 /// </exception>
438 public void AddComponent<T>(LifestyleType lifestyle)
440 Type classType = typeof(T);
441 AddComponent(classType.FullName, classType, lifestyle);
444 /// <summary>
445 /// Adds a concrete class
446 /// as a component with the specified <paramref name="lifestyle"/>.
447 /// </summary>
448 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
449 /// <param name="overwriteLifestyle">If <see langword="true"/>, then ignores all other configurations
450 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.</param>
451 /// <remarks>
452 /// If you have indicated a lifestyle for the specified T using
453 /// attributes, this method will not overwrite that lifestyle. To do that, use the
454 /// <see cref="AddComponent(string,Type,LifestyleType,bool)"/> method.
455 /// </remarks>
456 /// <exception cref="ArgumentException"/>
457 /// Thrown if
458 /// <paramref name="lifestyle"/>
459 /// is
460 /// <see cref="LifestyleType.Undefined"/>
461 /// .
462 public void AddComponent<T>(LifestyleType lifestyle, bool overwriteLifestyle)
464 Type classType = typeof(T);
465 AddComponent(classType.FullName, classType, lifestyle, overwriteLifestyle);
468 /// <summary>
469 /// Adds a concrete class and an interface
470 /// as a component
471 /// </summary>
472 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
473 public void AddComponent<T>(Type serviceType)
475 Type classType = typeof(T);
476 AddComponent(classType.FullName, serviceType, classType);
479 /// <summary>
480 /// Adds a concrete class and an interface
481 /// as a component with the specified <paramref name="lifestyle"/>.
482 /// </summary>
483 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
484 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
485 /// <remarks>
486 /// If you have indicated a lifestyle for the specified T using
487 /// attributes, this method will not overwrite that lifestyle. To do that, use the
488 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
489 /// </remarks>
490 /// <exception cref="ArgumentNullException">
491 /// are <see langword="null"/>.
492 /// </exception>
493 /// <exception cref="ArgumentException">
494 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
495 /// </exception>
496 public void AddComponent<T>(Type serviceType, LifestyleType lifestyle)
498 Type classType = typeof(T);
499 AddComponent(classType.FullName, serviceType, classType, lifestyle);
502 /// <summary>
503 /// Adds a concrete class and an interface
504 /// as a component with the specified <paramref name="lifestyle"/>.
505 /// </summary>
506 /// <param name="serviceType">The service <see cref="Type"/> that this component implements.</param>
507 /// <param name="lifestyle">The specified <see cref="LifestyleType"/> for the component.</param>
508 /// <param name="overwriteLifestyle">If <see langword="true"/>, then ignores all other configurations
509 /// for lifestyle and uses the value in the <paramref name="lifestyle"/> parameter.</param>
510 /// <remarks>
511 /// attributes, this method will not overwrite that lifestyle. To do that, use the
512 /// <see cref="AddComponent(string,Type,Type,LifestyleType,bool)"/> method.
513 /// </remarks>
514 /// <exception cref="ArgumentNullException">
515 /// are <see langword="null"/>.
516 /// </exception>
517 /// <exception cref="ArgumentException">
518 /// Thrown if <paramref name="lifestyle"/> is <see cref="LifestyleType.Undefined"/>.
519 /// </exception>
520 public void AddComponent<T>(Type serviceType, LifestyleType lifestyle, bool overwriteLifestyle)
522 Type classType = typeof(T);
523 AddComponent(classType.FullName, serviceType, classType, lifestyle, overwriteLifestyle);
526 /// <summary>
527 /// Used mostly by facilities. Adds an instance
528 /// to be used as a component.
529 /// </summary>
530 /// <param name="instance"></param>
531 public void AddComponentInstance<T>(object instance)
533 Type serviceType = typeof(T);
534 AddComponentInstance(serviceType.FullName, serviceType, instance);
537 /// <summary>
538 /// Used mostly by facilities. Adds an instance
539 /// to be used as a component.
540 /// </summary>
541 /// <param name="serviceType"></param>
542 /// <param name="instance"></param>
543 public void AddComponentInstance<T>(Type serviceType, object instance)
545 Type classType = typeof(T);
546 AddComponentInstance(classType.FullName, serviceType, classType, instance);
549 /// <summary>
550 /// Adds a component to be registered with the <see cref="IKernel"/>
551 /// using a fluent interface.
552 /// </summary>
553 /// <typeparam name="S">The service <see cref="Type"/> to manage.</typeparam>
554 /// <returns>The <see cref="ComponentRegistration{S,T}"/></returns>
555 public ComponentRegistration<S,IKernel> AddComponentEx<S>()
557 return new ComponentRegistration<S,IKernel>(this, this);
560 /// <summary>
561 /// Returns the component instance by the service type
562 /// using dynamic arguments
563 /// </summary>
564 /// <param name="arguments"></param>
565 /// <returns></returns>
566 public T Resolve<T>(IDictionary arguments)
568 Type serviceType = typeof(T);
569 return (T)Resolve(serviceType, arguments);
572 /// <summary>
573 /// Returns the component instance by the component key
574 /// </summary>
575 /// <returns></returns>
576 public T Resolve<T>()
578 Type serviceType = typeof(T);
579 return (T)Resolve(serviceType);
582 /// <summary>
583 /// Returns true if the specified component was
584 /// found and could be removed (i.e. no other component depends on it)
585 /// </summary>
586 /// <param name="key">The component's key</param>
587 /// <returns></returns>
588 public virtual bool RemoveComponent(String key)
590 if (key == null) throw new ArgumentNullException("key");
592 if (NamingSubSystem.Contains(key))
594 IHandler handler = GetHandler(key);
596 if (handler.ComponentModel.Dependers.Length == 0)
598 NamingSubSystem.UnRegister(key);
600 IHandler[] assignableHandlers = GetAssignableHandlers(handler.ComponentModel.Service);
601 if (assignableHandlers.Length > 0)
603 NamingSubSystem[handler.ComponentModel.Service] = assignableHandlers[0];
605 else
607 NamingSubSystem.UnRegister(handler.ComponentModel.Service);
610 foreach (ComponentModel model in handler.ComponentModel.Dependents)
612 model.RemoveDepender(handler.ComponentModel);
615 RaiseComponentUnregistered(key, handler);
617 DisposeHandler(handler);
619 return true;
621 else
623 // We can't remove this component as there are
624 // others which depends on it
626 return false;
630 if (Parent != null)
632 return Parent.RemoveComponent(key);
635 return false;
638 public virtual bool HasComponent(String key)
640 if (key == null) throw new ArgumentNullException("key");
642 if (NamingSubSystem.Contains(key))
644 return true;
647 if (Parent != null)
649 return Parent.HasComponent(key);
652 return false;
655 public virtual bool HasComponent(Type serviceType)
657 if (serviceType == null) throw new ArgumentNullException("serviceType");
659 if (NamingSubSystem.Contains(serviceType))
661 return true;
664 if (serviceType.IsGenericType && NamingSubSystem.Contains(serviceType.GetGenericTypeDefinition()))
666 return true;
669 if (Parent != null)
671 return Parent.HasComponent(serviceType);
674 return false;
677 public virtual object this[String key]
681 if (key == null) throw new ArgumentNullException("key");
683 if (!HasComponent(key))
685 throw new ComponentNotFoundException(key);
688 IHandler handler = GetHandler(key);
690 return ResolveComponent(handler);
694 public virtual object this[Type service]
698 if (service == null) throw new ArgumentNullException("service");
700 if (!HasComponent(service))
702 throw new ComponentNotFoundException(service);
705 IHandler handler = GetHandler(service);
707 return ResolveComponent(handler, service);
711 /// <summary>
712 /// Returns the component instance by the service type
713 /// </summary>
714 public object Resolve(Type service)
716 if (service == null) throw new ArgumentNullException("service");
718 return this[service];
721 /// <summary>
722 /// Returns all the valid component instances by
723 /// the service type
724 /// </summary>
725 /// <param name="service">The service type</param>
726 /// <param name="arguments">Arguments to resolve the services</param>
727 public Array ResolveAll(Type service, IDictionary arguments)
729 ArrayList list = new ArrayList();
730 IHandler[] handlers = GetAssignableHandlers(service);
731 foreach (IHandler handler in handlers)
733 object component = ResolveComponent(handler, service, arguments);
734 list.Add(component);
736 return list.ToArray(service);
739 /// <summary>
740 /// Returns the component instance by the service type
741 /// using dynamic arguments
742 /// </summary>
743 /// <param name="service"></param>
744 /// <param name="arguments"></param>
745 /// <returns></returns>
746 public object Resolve(Type service, IDictionary arguments)
748 if (service == null) throw new ArgumentNullException("service");
749 if (arguments == null) throw new ArgumentNullException("arguments");
751 if (!HasComponent(service))
753 throw new ComponentNotFoundException(service);
756 IHandler handler = GetHandler(service);
758 return ResolveComponent(handler, service, arguments);
761 /// <summary>
762 /// Returns the component instance by the component key
763 /// using dynamic arguments
764 /// </summary>
765 /// <param name="key"></param>
766 /// <param name="arguments"></param>
767 /// <returns></returns>
768 public object Resolve(string key, IDictionary arguments)
770 if (key == null) throw new ArgumentNullException("key");
771 if (arguments == null) throw new ArgumentNullException("arguments");
773 if (!HasComponent(key))
775 throw new ComponentNotFoundException(key);
778 IHandler handler = GetHandler(key);
780 return ResolveComponent(handler, arguments);
784 public void RegisterCustomDependencies(Type service, IDictionary dependencies)
786 IHandler handler = GetHandler(service);
788 foreach (DictionaryEntry entry in dependencies)
790 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
794 public void RegisterCustomDependencies(String key, IDictionary dependencies)
796 IHandler handler = GetHandler(key);
798 foreach (DictionaryEntry entry in dependencies)
800 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
804 /// <summary>
805 /// Returns a component instance by the key
806 /// </summary>
807 /// <param name="key"></param>
808 /// <param name="service"></param>
809 /// <returns></returns>
810 public virtual object Resolve(String key, Type service)
812 if (key == null) throw new ArgumentNullException("key");
813 if (service == null) throw new ArgumentNullException("service");
815 if (!HasComponent(key))
817 throw new ComponentNotFoundException(key);
820 IHandler handler = GetHandler(key);
822 return ResolveComponent(handler, service);
826 public TService[] ResolveServices<TService>()
828 List<TService> services = new List<TService>();
829 IHandler[] handlers = GetHandlers(typeof(TService));
831 foreach (IHandler handler in handlers)
833 if (handler.CurrentState == HandlerState.Valid)
835 services.Add((TService)ResolveComponent(handler));
839 return services.ToArray();
842 /// <summary>
843 /// Returns a component instance by the key
844 /// </summary>
845 /// <param name="key"></param>
846 /// <param name="service"></param>
847 /// <param name="arguments"></param>
848 /// <returns></returns>
849 public virtual object Resolve(String key, Type service, IDictionary arguments)
851 if (key == null) throw new ArgumentNullException("key");
852 if (service == null) throw new ArgumentNullException("service");
854 if (!HasComponent(key))
856 throw new ComponentNotFoundException(key);
859 IHandler handler = GetHandler(key);
861 return ResolveComponent(handler, service, arguments);
864 public virtual void ReleaseComponent(object instance)
866 if (ReleasePolicy.HasTrack(instance))
868 ReleasePolicy.Release(instance);
870 else
872 if (Parent != null)
874 Parent.ReleaseComponent(instance);
879 public IHandlerFactory HandlerFactory
881 get { return handlerFactory; }
884 public IComponentModelBuilder ComponentModelBuilder
886 get { return modelBuilder; }
887 set { modelBuilder = value; }
890 public IProxyFactory ProxyFactory
892 get { return proxyFactory; }
893 set { proxyFactory = value; }
896 public virtual IConfigurationStore ConfigurationStore
898 get { return GetSubSystem(SubSystemConstants.ConfigurationStoreKey) as IConfigurationStore; }
899 set { AddSubSystem(SubSystemConstants.ConfigurationStoreKey, value); }
902 public virtual IHandler GetHandler(String key)
904 if (key == null) throw new ArgumentNullException("key");
906 IHandler handler = NamingSubSystem.GetHandler(key);
908 if (handler == null && Parent != null)
910 handler = WrapParentHandler(Parent.GetHandler(key));
913 return handler;
916 public virtual IHandler GetHandler(Type service)
918 if (service == null) throw new ArgumentNullException("service");
920 IHandler handler = NamingSubSystem.GetHandler(service);
922 if (handler == null && service.IsGenericType)
924 handler = NamingSubSystem.GetHandler(service.GetGenericTypeDefinition());
927 if (handler == null && Parent != null)
929 handler = WrapParentHandler(Parent.GetHandler(service));
932 return handler;
935 /// <summary>
936 /// Return handlers for components that
937 /// implements the specified service.
938 /// </summary>
939 /// <param name="service"></param>
940 /// <returns></returns>
941 public virtual IHandler[] GetHandlers(Type service)
943 IHandler[] result = NamingSubSystem.GetHandlers(service);
945 // a complete generic type, Foo<Bar>, need to check if Foo<T> is registered
946 if (service.IsGenericType && !service.IsGenericTypeDefinition)
948 IHandler[] genericResult = NamingSubSystem.GetHandlers(service.GetGenericTypeDefinition());
950 if (result.Length > 0)
952 IHandler[] mergedResult = new IHandler[result.Length + genericResult.Length];
953 result.CopyTo(mergedResult, 0);
954 genericResult.CopyTo(mergedResult, result.Length);
955 result = mergedResult;
957 else
959 result = genericResult;
963 // If a parent kernel exists, we merge both results
964 if (Parent != null)
966 IHandler[] parentResult = Parent.GetHandlers(service);
968 if (parentResult.Length > 0)
970 IHandler[] newResult = new IHandler[result.Length + parentResult.Length];
971 result.CopyTo(newResult, 0);
972 parentResult.CopyTo(newResult, result.Length);
973 result = newResult;
977 return result;
980 /// <summary>
981 /// Return handlers for components that
982 /// implements the specified service.
983 /// The check is made using IsAssignableFrom
984 /// </summary>
985 /// <param name="service"></param>
986 /// <returns></returns>
987 public virtual IHandler[] GetAssignableHandlers(Type service)
989 return NamingSubSystem.GetAssignableHandlers(service);
992 public virtual IReleasePolicy ReleasePolicy
994 get { return releaserPolicy; }
995 set { releaserPolicy = value; }
998 public virtual void AddFacility(String key, IFacility facility)
1000 if (key == null) throw new ArgumentNullException("key");
1001 if (facility == null) throw new ArgumentNullException("facility");
1003 facility.Init(this, ConfigurationStore.GetFacilityConfiguration(key));
1005 facilities.Add(facility);
1008 /// <summary>
1009 /// Returns the facilities registered on the kernel.
1010 /// </summary>
1011 /// <returns></returns>
1012 public virtual IFacility[] GetFacilities()
1014 IFacility[] list = new IFacility[facilities.Count];
1015 facilities.CopyTo(list, 0);
1016 return list;
1019 public virtual void AddSubSystem(String key, ISubSystem subsystem)
1021 if (key == null) throw new ArgumentNullException("key");
1022 if (subsystem == null) throw new ArgumentNullException("facility");
1024 subsystem.Init(this);
1025 subsystems[key] = subsystem;
1028 public virtual ISubSystem GetSubSystem(String key)
1030 if (key == null) throw new ArgumentNullException("key");
1032 return subsystems[key] as ISubSystem;
1035 public virtual void AddChildKernel(IKernel childKernel)
1037 if (childKernel == null) throw new ArgumentNullException("childKernel");
1039 childKernel.Parent = this;
1040 childKernels.Add(childKernel);
1043 public virtual IKernel Parent
1045 get { return parentKernel; }
1048 // TODO: should the raise add/removed as child kernel methods be invoked from within the subscriber/unsubscribe methods?
1050 if (value == null)
1052 if (parentKernel != null)
1054 UnsubscribeFromParentKernel();
1055 RaiseRemovedAsChildKernel();
1058 parentKernel = null;
1060 else
1062 if ((parentKernel != value) && (parentKernel != null))
1064 throw new KernelException(
1065 "You can not change the kernel parent once set, use the RemoveChildKernel and AddChildKernel methods together to achieve this.");
1067 parentKernel = value;
1068 SubscribeToParentKernel();
1069 RaiseAddedAsChildKernel();
1074 public IDependencyResolver Resolver
1076 get { return resolver; }
1079 public virtual IComponentActivator CreateComponentActivator(ComponentModel model)
1081 if (model == null) throw new ArgumentNullException("model");
1083 IComponentActivator activator;
1085 if (model.CustomComponentActivator == null)
1087 activator = new DefaultComponentActivator(model, this,
1088 new ComponentInstanceDelegate(RaiseComponentCreated),
1089 new ComponentInstanceDelegate(RaiseComponentDestroyed));
1091 else
1095 activator = (IComponentActivator)
1096 Activator.CreateInstance(model.CustomComponentActivator,
1097 new object[]
1099 model,
1100 this,
1101 new ComponentInstanceDelegate(RaiseComponentCreated),
1102 new ComponentInstanceDelegate(RaiseComponentDestroyed)
1105 catch (Exception e)
1107 throw new KernelException("Could not instantiate custom activator", e);
1111 return activator;
1114 /// <summary>
1115 /// Graph of components and iteractions.
1116 /// </summary>
1117 public GraphNode[] GraphNodes
1121 GraphNode[] nodes = new GraphNode[NamingSubSystem.ComponentCount];
1123 int index = 0;
1125 IHandler[] handlers = NamingSubSystem.GetHandlers();
1127 foreach (IHandler handler in handlers)
1129 nodes[index++] = handler.ComponentModel;
1132 return nodes;
1136 public virtual void RemoveChildKernel(IKernel childKernel)
1138 if (childKernel == null) throw new ArgumentNullException("childKernel");
1139 childKernel.Parent = null;
1140 childKernels.Remove(childKernel);
1143 #endregion
1145 #region IServiceProviderEx Members
1147 /// <summary>
1148 /// Gets the service object of the specified type.
1149 /// </summary>
1151 /// <returns>
1152 /// A service object of type serviceType.
1153 /// </returns>
1155 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
1156 public object GetService(Type serviceType)
1158 return Resolve(serviceType);
1161 /// <summary>
1162 /// Gets the service object of the specified type.
1163 /// </summary>
1165 /// <returns>
1166 /// A service object of type serviceType.
1167 /// </returns>
1168 public T GetService<T>()
1170 Type serviceType = typeof(T);
1171 return (T)Resolve(serviceType);
1174 #endregion
1176 #region IDisposable Members
1178 /// <summary>
1179 /// Starts the process of component disposal.
1180 /// </summary>
1181 public virtual void Dispose()
1183 DisposeSubKernels();
1184 TerminateFacilities();
1185 DisposeComponentsInstancesWithinTracker();
1186 DisposeHandlers();
1187 UnsubscribeFromParentKernel();
1190 private void TerminateFacilities()
1192 foreach (IFacility facility in facilities)
1194 facility.Terminate();
1198 private void DisposeHandlers()
1200 GraphNode[] nodes = GraphNodes;
1201 IVertex[] vertices = TopologicalSortAlgo.Sort(nodes);
1203 for (int i = 0; i < vertices.Length; i++)
1205 ComponentModel model = (ComponentModel)vertices[i];
1207 // Prevent the removal of a component that belongs
1208 // to other container
1209 if (!NamingSubSystem.Contains(model.Name)) continue;
1211 RemoveComponent(model.Name);
1215 private void UnsubscribeFromParentKernel()
1217 if (parentKernel != null)
1219 parentKernel.HandlerRegistered -= new HandlerDelegate(HandlerRegisteredOnParentKernel);
1220 parentKernel.ComponentRegistered -= new ComponentDataDelegate(RaiseComponentRegistered);
1221 parentKernel.ComponentUnregistered -= new ComponentDataDelegate(RaiseComponentUnregistered);
1225 private void SubscribeToParentKernel()
1227 if (parentKernel != null)
1229 parentKernel.HandlerRegistered += new HandlerDelegate(HandlerRegisteredOnParentKernel);
1230 parentKernel.ComponentRegistered += new ComponentDataDelegate(RaiseComponentRegistered);
1231 parentKernel.ComponentUnregistered += new ComponentDataDelegate(RaiseComponentUnregistered);
1235 private void HandlerRegisteredOnParentKernel(IHandler handler, ref bool stateChanged)
1237 RaiseHandlerRegistered(handler);
1240 private void DisposeComponentsInstancesWithinTracker()
1242 ReleasePolicy.Dispose();
1245 private void DisposeSubKernels()
1247 foreach (IKernel childKernel in childKernels)
1249 childKernel.Dispose();
1253 protected void DisposeHandler(IHandler handler)
1255 if (handler == null) return;
1257 if (handler is IDisposable)
1259 ((IDisposable)handler).Dispose();
1263 #endregion
1265 #region Protected members
1267 protected virtual IHandler WrapParentHandler(IHandler parentHandler)
1269 if (parentHandler == null) return null;
1271 // This has a very destructive side-effect. While the goal is to resolve on same-level containers,
1272 // the resolver will invoke GetHandler recursively, leading to stack overflows
1273 // return new ParentHandlerWithChildResolver(parentHandler, Resolver);
1274 return parentHandler;
1277 protected INamingSubSystem NamingSubSystem
1279 get { return GetSubSystem(SubSystemConstants.NamingKey) as INamingSubSystem; }
1282 protected void RegisterHandler(String key, IHandler handler)
1284 RegisterHandler(key, handler, false);
1287 protected void RegisterHandler(String key, IHandler handler, bool skipRegistration)
1289 if (!skipRegistration)
1291 NamingSubSystem.Register(key, handler);
1294 base.RaiseHandlerRegistered(handler);
1295 base.RaiseComponentRegistered(key, handler);
1298 protected object ResolveComponent(IHandler handler)
1300 return ResolveComponent(handler, handler.ComponentModel.Service);
1303 protected object ResolveComponent(IHandler handler, Type service)
1305 return ResolveComponent(handler, service, null);
1308 protected object ResolveComponent(IHandler handler, IDictionary additionalArguments)
1310 return ResolveComponent(handler, handler.ComponentModel.Service, additionalArguments);
1313 protected object ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments)
1315 CreationContext context = CreateCreationContext(handler, service, additionalArguments);
1317 object instance = handler.Resolve(context);
1319 ReleasePolicy.Track(instance, handler);
1321 return instance;
1324 protected CreationContext CreateCreationContext(IHandler handler, Type typeToExtractGenericArguments,
1325 IDictionary additionalArguments)
1327 return new CreationContext(handler, typeToExtractGenericArguments, additionalArguments);
1330 #endregion
1332 #region Serialization and Deserialization
1334 public override void GetObjectData(SerializationInfo info, StreamingContext context)
1336 base.GetObjectData(info, context);
1338 MemberInfo[] members = FormatterServices.GetSerializableMembers(GetType(), context);
1340 object[] kernelmembers = FormatterServices.GetObjectData(this, members);
1342 info.AddValue("members", kernelmembers, typeof(object[]));
1345 void IDeserializationCallback.OnDeserialization(object sender)
1349 #endregion