Fixing an issue with output parameters that are of type IntPtr
[castle.git] / InversionOfControl / Castle.MicroKernel / DefaultKernel.cs
blob94c5ce128450be75c5208aed4d1536a5298e5414
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 Type service = handler.ComponentModel.Service;
621 IHandler[] assignableHandlers = NamingSubSystem.GetAssignableHandlers(service);
622 if (assignableHandlers.Length > 0)
624 NamingSubSystem[handler.ComponentModel.Service] = assignableHandlers[0];
626 else
628 NamingSubSystem.UnRegister(service);
631 foreach (ComponentModel model in handler.ComponentModel.Dependents)
633 model.RemoveDepender(handler.ComponentModel);
636 RaiseComponentUnregistered(key, handler);
638 DisposeHandler(handler);
640 return true;
642 else
644 // We can't remove this component as there are
645 // others which depends on it
647 return false;
651 if (Parent != null)
653 return Parent.RemoveComponent(key);
656 return false;
659 public virtual bool HasComponent(String key)
661 if (key == null) throw new ArgumentNullException("key");
663 if (NamingSubSystem.Contains(key))
665 return true;
668 if (Parent != null)
670 return Parent.HasComponent(key);
673 return false;
676 public virtual bool HasComponent(Type serviceType)
678 if (serviceType == null) throw new ArgumentNullException("serviceType");
680 if (NamingSubSystem.Contains(serviceType))
682 return true;
685 if (serviceType.IsGenericType && NamingSubSystem.Contains(serviceType.GetGenericTypeDefinition()))
687 return true;
690 if (Parent != null)
692 return Parent.HasComponent(serviceType);
695 return false;
698 public virtual object this[String key]
702 if (key == null) throw new ArgumentNullException("key");
704 if (!HasComponent(key))
706 throw new ComponentNotFoundException(key);
709 IHandler handler = GetHandler(key);
711 return ResolveComponent(handler);
715 public virtual object this[Type service]
719 if (service == null) throw new ArgumentNullException("service");
721 if (!HasComponent(service))
723 throw new ComponentNotFoundException(service);
726 IHandler handler = GetHandler(service);
728 return ResolveComponent(handler, service);
732 /// <summary>
733 /// Returns the component instance by the service type
734 /// </summary>
735 public object Resolve(Type service)
737 if (service == null) throw new ArgumentNullException("service");
739 return this[service];
742 /// <summary>
743 /// Returns all the valid component instances by
744 /// the service type
745 /// </summary>
746 /// <param name="service">The service type</param>
747 /// <param name="arguments">Arguments to resolve the services</param>
748 public Array ResolveAll(Type service, IDictionary arguments)
750 ArrayList list = new ArrayList();
751 IHandler[] handlers = GetAssignableHandlers(service);
752 foreach (IHandler handler in handlers)
754 if(handler.CurrentState!=HandlerState.Valid)
755 continue;
757 object component = ResolveComponent(handler, service, arguments);
758 list.Add(component);
760 return list.ToArray(service);
763 /// <summary>
764 /// Returns all the valid component instances by
765 /// the service type
766 /// </summary>
767 /// <param name="service">The service type</param>
768 /// <param name="argumentsAsAnonymousType">Arguments to resolve the services</param>
769 public Array ResolveAll(Type service, object argumentsAsAnonymousType)
771 return ResolveAll(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
775 /// <summary>
776 /// Returns component instances that implement TService
777 /// </summary>
778 /// <typeparam name="TService"></typeparam>
779 /// <param name="argumentsAsAnonymousType"></param>
780 /// <returns></returns>
781 public TService[] ResolveAll<TService>(object argumentsAsAnonymousType)
783 return (TService[]) ResolveAll(typeof(TService), argumentsAsAnonymousType);
786 /// <summary>
787 /// Returns component instances that implement TService
788 /// </summary>
789 /// <typeparam name="TService"></typeparam>
790 /// <param name="arguments"></param>
791 /// <returns></returns>
792 public TService[] ResolveAll<TService>(IDictionary arguments)
794 return (TService[])ResolveAll(typeof(TService), arguments);
799 /// <summary>
800 /// Returns the component instance by the service type
801 /// using dynamic arguments
802 /// </summary>
803 /// <param name="service"></param>
804 /// <param name="arguments"></param>
805 /// <returns></returns>
806 public object Resolve(Type service, IDictionary arguments)
808 if (service == null) throw new ArgumentNullException("service");
809 if (arguments == null) throw new ArgumentNullException("arguments");
811 if (!HasComponent(service))
813 throw new ComponentNotFoundException(service);
816 IHandler handler = GetHandler(service);
818 return ResolveComponent(handler, service, arguments);
821 /// <summary>
822 /// Returns the component instance by the service type
823 /// using dynamic arguments
824 /// </summary>
825 /// <param name="service"></param>
826 /// <param name="argumentsAsAnonymousType"></param>
827 /// <returns></returns>
828 public object Resolve(Type service, object argumentsAsAnonymousType)
830 return Resolve(service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
833 /// <summary>
834 /// Returns the component instance by the component key
835 /// using dynamic arguments
836 /// </summary>
837 /// <param name="key"></param>
838 /// <param name="arguments"></param>
839 /// <returns></returns>
840 public object Resolve(string key, IDictionary arguments)
842 if (key == null) throw new ArgumentNullException("key");
843 if (arguments == null) throw new ArgumentNullException("arguments");
845 if (!HasComponent(key))
847 throw new ComponentNotFoundException(key);
850 IHandler handler = GetHandler(key);
852 return ResolveComponent(handler, arguments);
855 /// <summary>
856 /// Returns the component instance by the component key
857 /// using dynamic arguments
858 /// </summary>
859 /// <param name="key"></param>
860 /// <param name="argumentsAsAnonymousType"></param>
861 /// <returns></returns>
862 public object Resolve(string key, object argumentsAsAnonymousType)
864 return Resolve(key, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
867 /// <summary>
868 /// Associates objects with a component handler,
869 /// allowing it to use the specified dictionary
870 /// when resolving dependencies
871 /// </summary>
872 /// <param name="service"></param>
873 /// <param name="dependencies"></param>
874 public void RegisterCustomDependencies(Type service, IDictionary dependencies)
876 IHandler handler = GetHandler(service);
878 foreach (DictionaryEntry entry in dependencies)
880 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
884 /// <summary>
885 /// Associates objects with a component handler,
886 /// allowing it to use the specified dictionary
887 /// when resolving dependencies
888 /// </summary>
889 /// <param name="service"></param>
890 /// <param name="dependenciesAsAnonymousType"></param>
891 public void RegisterCustomDependencies(Type service, object dependenciesAsAnonymousType)
893 RegisterCustomDependencies(service, new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType));
896 /// <summary>
897 /// Associates objects with a component handler,
898 /// allowing it to use the specified dictionary
899 /// when resolving dependencies
900 /// </summary>
901 /// <param name="key"></param>
902 /// <param name="dependencies"></param>
903 public void RegisterCustomDependencies(String key, IDictionary dependencies)
905 IHandler handler = GetHandler(key);
907 foreach (DictionaryEntry entry in dependencies)
909 handler.AddCustomDependencyValue(entry.Key.ToString(), entry.Value);
913 /// <summary>
914 /// Associates objects with a component handler,
915 /// allowing it to use the specified dictionary
916 /// when resolving dependencies
917 /// </summary>
918 /// <param name="key"></param>
919 /// <param name="dependenciesAsAnonymousType"></param>
920 public void RegisterCustomDependencies(String key, object dependenciesAsAnonymousType)
922 RegisterCustomDependencies(key, new ReflectionBasedDictionaryAdapter(dependenciesAsAnonymousType));
925 /// <summary>
926 /// Returns a component instance by the key
927 /// </summary>
928 /// <param name="key"></param>
929 /// <param name="service"></param>
930 /// <returns></returns>
931 public virtual object Resolve(String key, Type service)
933 if (key == null) throw new ArgumentNullException("key");
934 if (service == null) throw new ArgumentNullException("service");
936 if (!HasComponent(key))
938 throw new ComponentNotFoundException(key);
941 IHandler handler = GetHandler(key);
943 return ResolveComponent(handler, service);
947 /// <summary>
948 /// Returns component instances that implement TService
949 /// </summary>
950 /// <typeparam name="TService"></typeparam>
951 /// <returns></returns>
952 public TService[] ResolveAll<TService>()
954 return (TService[]) ResolveAll(typeof (TService), new Hashtable());
957 /// <summary>
958 /// Returns a component instance by the key
959 /// </summary>
960 /// <param name="key"></param>
961 /// <param name="service"></param>
962 /// <param name="arguments"></param>
963 /// <returns></returns>
964 public virtual object Resolve(String key, Type service, IDictionary arguments)
966 if (key == null) throw new ArgumentNullException("key");
967 if (service == null) throw new ArgumentNullException("service");
969 if (!HasComponent(key))
971 throw new ComponentNotFoundException(key);
974 IHandler handler = GetHandler(key);
976 return ResolveComponent(handler, service, arguments);
979 /// <summary>
980 /// Resolves the specified key.
981 /// </summary>
982 /// <param name="key">The key.</param>
983 /// <param name="service">The service.</param>
984 /// <param name="argumentsAsAnonymousType">Type of the arguments as anonymous.</param>
985 /// <returns></returns>
986 public virtual object Resolve(String key, Type service, object argumentsAsAnonymousType)
988 return Resolve(key, service, new ReflectionBasedDictionaryAdapter(argumentsAsAnonymousType));
991 /// <summary>
992 /// Releases a component instance. This allows
993 /// the kernel to execute the proper decomission
994 /// lifecycles on the component instance.
995 /// </summary>
996 /// <param name="instance"></param>
997 public virtual void ReleaseComponent(object instance)
999 if (ReleasePolicy.HasTrack(instance))
1001 ReleasePolicy.Release(instance);
1003 else
1005 if (Parent != null)
1007 Parent.ReleaseComponent(instance);
1012 public IHandlerFactory HandlerFactory
1014 get { return handlerFactory; }
1017 public IComponentModelBuilder ComponentModelBuilder
1019 get { return modelBuilder; }
1020 set { modelBuilder = value; }
1023 public IProxyFactory ProxyFactory
1025 get { return proxyFactory; }
1026 set { proxyFactory = value; }
1029 public virtual IConfigurationStore ConfigurationStore
1031 get { return GetSubSystem(SubSystemConstants.ConfigurationStoreKey) as IConfigurationStore; }
1032 set { AddSubSystem(SubSystemConstants.ConfigurationStoreKey, value); }
1035 public virtual IHandler GetHandler(String key)
1037 if (key == null) throw new ArgumentNullException("key");
1039 IHandler handler = NamingSubSystem.GetHandler(key);
1041 if (handler == null && Parent != null)
1043 handler = WrapParentHandler(Parent.GetHandler(key));
1046 return handler;
1049 public virtual IHandler GetHandler(Type service)
1051 if (service == null) throw new ArgumentNullException("service");
1053 IHandler handler = NamingSubSystem.GetHandler(service);
1055 if (handler == null && service.IsGenericType)
1057 handler = NamingSubSystem.GetHandler(service.GetGenericTypeDefinition());
1060 if (handler == null && Parent != null)
1062 handler = WrapParentHandler(Parent.GetHandler(service));
1065 return handler;
1068 /// <summary>
1069 /// Return handlers for components that
1070 /// implements the specified service.
1071 /// </summary>
1072 /// <param name="service"></param>
1073 /// <returns></returns>
1074 public virtual IHandler[] GetHandlers(Type service)
1076 IHandler[] result = NamingSubSystem.GetHandlers(service);
1078 // a complete generic type, Foo<Bar>, need to check if Foo<T> is registered
1079 if (service.IsGenericType && !service.IsGenericTypeDefinition)
1081 IHandler[] genericResult = NamingSubSystem.GetHandlers(service.GetGenericTypeDefinition());
1083 if (result.Length > 0)
1085 IHandler[] mergedResult = new IHandler[result.Length + genericResult.Length];
1086 result.CopyTo(mergedResult, 0);
1087 genericResult.CopyTo(mergedResult, result.Length);
1088 result = mergedResult;
1090 else
1092 result = genericResult;
1096 // If a parent kernel exists, we merge both results
1097 if (Parent != null)
1099 IHandler[] parentResult = Parent.GetHandlers(service);
1101 if (parentResult.Length > 0)
1103 IHandler[] newResult = new IHandler[result.Length + parentResult.Length];
1104 result.CopyTo(newResult, 0);
1105 parentResult.CopyTo(newResult, result.Length);
1106 result = newResult;
1110 return result;
1113 /// <summary>
1114 /// Return handlers for components that
1115 /// implements the specified service.
1116 /// The check is made using IsAssignableFrom
1117 /// </summary>
1118 /// <param name="service"></param>
1119 /// <returns></returns>
1120 public virtual IHandler[] GetAssignableHandlers(Type service)
1122 IHandler[] result = NamingSubSystem.GetAssignableHandlers(service);
1124 // If a parent kernel exists, we merge both results
1125 if (Parent != null)
1127 IHandler[] parentResult = Parent.GetAssignableHandlers(service);
1129 if (parentResult.Length > 0)
1131 IHandler[] newResult = new IHandler[result.Length + parentResult.Length];
1132 result.CopyTo(newResult, 0);
1133 parentResult.CopyTo(newResult, result.Length);
1134 result = newResult;
1138 return result;
1141 public virtual IReleasePolicy ReleasePolicy
1143 get { return releaserPolicy; }
1144 set { releaserPolicy = value; }
1147 public virtual void AddFacility(String key, IFacility facility)
1149 if (key == null) throw new ArgumentNullException("key");
1150 if (facility == null) throw new ArgumentNullException("facility");
1152 facility.Init(this, ConfigurationStore.GetFacilityConfiguration(key));
1154 facilities.Add(facility);
1157 public void AddFacility<T>(String key) where T : IFacility, new()
1159 AddFacility(key, new T());
1162 public void AddFacility<T>() where T : IFacility, new()
1164 AddFacility<T>(typeof(T).FullName);
1167 /// <summary>
1168 /// Returns the facilities registered on the kernel.
1169 /// </summary>
1170 /// <returns></returns>
1171 public virtual IFacility[] GetFacilities()
1173 IFacility[] list = new IFacility[facilities.Count];
1174 facilities.CopyTo(list, 0);
1175 return list;
1178 public virtual void AddSubSystem(String key, ISubSystem subsystem)
1180 if (key == null) throw new ArgumentNullException("key");
1181 if (subsystem == null) throw new ArgumentNullException("facility");
1183 subsystem.Init(this);
1184 subsystems[key] = subsystem;
1187 public virtual ISubSystem GetSubSystem(String key)
1189 if (key == null) throw new ArgumentNullException("key");
1191 return subsystems[key] as ISubSystem;
1194 public virtual void AddChildKernel(IKernel childKernel)
1196 if (childKernel == null) throw new ArgumentNullException("childKernel");
1198 childKernel.Parent = this;
1199 childKernels.Add(childKernel);
1202 public virtual IKernel Parent
1204 get { return parentKernel; }
1207 // TODO: should the raise add/removed as child kernel methods be invoked from within the subscriber/unsubscribe methods?
1209 if (value == null)
1211 if (parentKernel != null)
1213 UnsubscribeFromParentKernel();
1214 RaiseRemovedAsChildKernel();
1217 parentKernel = null;
1219 else
1221 if ((parentKernel != value) && (parentKernel != null))
1223 throw new KernelException(
1224 "You can not change the kernel parent once set, use the RemoveChildKernel and AddChildKernel methods together to achieve this.");
1226 parentKernel = value;
1227 SubscribeToParentKernel();
1228 RaiseAddedAsChildKernel();
1233 public IDependencyResolver Resolver
1235 get { return resolver; }
1238 public virtual IComponentActivator CreateComponentActivator(ComponentModel model)
1240 if (model == null) throw new ArgumentNullException("model");
1242 IComponentActivator activator;
1244 if (model.CustomComponentActivator == null)
1246 activator = new DefaultComponentActivator(model, this,
1247 new ComponentInstanceDelegate(RaiseComponentCreated),
1248 new ComponentInstanceDelegate(RaiseComponentDestroyed));
1250 else
1254 activator = (IComponentActivator)
1255 Activator.CreateInstance(model.CustomComponentActivator,
1256 new object[]
1258 model,
1259 this,
1260 new ComponentInstanceDelegate(RaiseComponentCreated),
1261 new ComponentInstanceDelegate(RaiseComponentDestroyed)
1264 catch (Exception e)
1266 throw new KernelException("Could not instantiate custom activator", e);
1270 return activator;
1273 /// <summary>
1274 /// Graph of components and iteractions.
1275 /// </summary>
1276 public GraphNode[] GraphNodes
1280 GraphNode[] nodes = new GraphNode[NamingSubSystem.ComponentCount];
1282 int index = 0;
1284 IHandler[] handlers = NamingSubSystem.GetHandlers();
1286 foreach (IHandler handler in handlers)
1288 nodes[index++] = handler.ComponentModel;
1291 return nodes;
1295 public virtual void RemoveChildKernel(IKernel childKernel)
1297 if (childKernel == null) throw new ArgumentNullException("childKernel");
1298 childKernel.Parent = null;
1299 childKernels.Remove(childKernel);
1302 #endregion
1304 #region IServiceProviderEx Members
1306 /// <summary>
1307 /// Gets the service object of the specified type.
1308 /// </summary>
1310 /// <returns>
1311 /// A service object of type serviceType.
1312 /// </returns>
1314 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
1315 public object GetService(Type serviceType)
1317 if (!HasComponent(serviceType))
1319 return null;
1322 return Resolve(serviceType);
1325 /// <summary>
1326 /// Gets the service object of the specified type.
1327 /// </summary>
1329 /// <returns>
1330 /// A service object of type serviceType.
1331 /// </returns>
1332 public T GetService<T>() where T : class
1334 Type serviceType = typeof(T);
1336 if (!HasComponent(serviceType))
1338 return null;
1341 return (T)Resolve(serviceType);
1344 #endregion
1346 #region IDisposable Members
1348 /// <summary>
1349 /// Starts the process of component disposal.
1350 /// </summary>
1351 public virtual void Dispose()
1353 DisposeSubKernels();
1354 TerminateFacilities();
1355 DisposeComponentsInstancesWithinTracker();
1356 DisposeHandlers();
1357 UnsubscribeFromParentKernel();
1360 private void TerminateFacilities()
1362 foreach (IFacility facility in facilities)
1364 facility.Terminate();
1368 private void DisposeHandlers()
1370 GraphNode[] nodes = GraphNodes;
1371 IVertex[] vertices = TopologicalSortAlgo.Sort(nodes);
1373 for (int i = 0; i < vertices.Length; i++)
1375 ComponentModel model = (ComponentModel)vertices[i];
1377 // Prevent the removal of a component that belongs
1378 // to other container
1379 if (!NamingSubSystem.Contains(model.Name)) continue;
1381 RemoveComponent(model.Name);
1385 private void UnsubscribeFromParentKernel()
1387 if (parentKernel != null)
1389 parentKernel.HandlerRegistered -= new HandlerDelegate(HandlerRegisteredOnParentKernel);
1390 parentKernel.ComponentRegistered -= new ComponentDataDelegate(RaiseComponentRegistered);
1391 parentKernel.ComponentUnregistered -= new ComponentDataDelegate(RaiseComponentUnregistered);
1395 private void SubscribeToParentKernel()
1397 if (parentKernel != null)
1399 parentKernel.HandlerRegistered += new HandlerDelegate(HandlerRegisteredOnParentKernel);
1400 parentKernel.ComponentRegistered += new ComponentDataDelegate(RaiseComponentRegistered);
1401 parentKernel.ComponentUnregistered += new ComponentDataDelegate(RaiseComponentUnregistered);
1405 private void HandlerRegisteredOnParentKernel(IHandler handler, ref bool stateChanged)
1407 RaiseHandlerRegistered(handler);
1410 private void DisposeComponentsInstancesWithinTracker()
1412 ReleasePolicy.Dispose();
1415 private void DisposeSubKernels()
1417 foreach (IKernel childKernel in childKernels)
1419 childKernel.Dispose();
1423 protected void DisposeHandler(IHandler handler)
1425 if (handler == null) return;
1427 if (handler is IDisposable)
1429 ((IDisposable)handler).Dispose();
1433 #endregion
1435 #region Protected members
1437 protected virtual IHandler WrapParentHandler(IHandler parentHandler)
1439 if (parentHandler == null) return null;
1441 // This has a very destructive side-effect. While the goal is to resolve on same-level containers,
1442 // the resolver will invoke GetHandler recursively, leading to stack overflows
1443 // return new ParentHandlerWithChildResolver(parentHandler, Resolver);
1444 return parentHandler;
1447 protected INamingSubSystem NamingSubSystem
1449 get { return GetSubSystem(SubSystemConstants.NamingKey) as INamingSubSystem; }
1452 protected void RegisterHandler(String key, IHandler handler)
1454 RegisterHandler(key, handler, false);
1457 protected void RegisterHandler(String key, IHandler handler, bool skipRegistration)
1459 if (!skipRegistration)
1461 NamingSubSystem.Register(key, handler);
1464 base.RaiseHandlerRegistered(handler);
1465 base.RaiseComponentRegistered(key, handler);
1468 protected object ResolveComponent(IHandler handler)
1470 return ResolveComponent(handler, handler.ComponentModel.Service);
1473 protected object ResolveComponent(IHandler handler, Type service)
1475 return ResolveComponent(handler, service, null);
1478 protected object ResolveComponent(IHandler handler, IDictionary additionalArguments)
1480 return ResolveComponent(handler, handler.ComponentModel.Service, additionalArguments);
1483 protected object ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments)
1485 CreationContext context = CreateCreationContext(handler, service, additionalArguments);
1487 object instance = handler.Resolve(context);
1489 ReleasePolicy.Track(instance, handler);
1491 return instance;
1494 protected CreationContext CreateCreationContext(IHandler handler, Type typeToExtractGenericArguments,
1495 IDictionary additionalArguments)
1497 return new CreationContext(handler, typeToExtractGenericArguments, additionalArguments);
1500 #endregion
1502 #region Serialization and Deserialization
1504 public override void GetObjectData(SerializationInfo info, StreamingContext context)
1506 base.GetObjectData(info, context);
1508 MemberInfo[] members = FormatterServices.GetSerializableMembers(GetType(), context);
1510 object[] kernelmembers = FormatterServices.GetObjectData(this, members);
1512 info.AddValue("members", kernelmembers, typeof(object[]));
1515 void IDeserializationCallback.OnDeserialization(object sender)
1519 #endregion