- Applied Ron Grabowski's patch fixing IOC-89
[castle.git] / InversionOfControl / Castle.Windsor / WindsorContainer.cs
bloba9cebf9b2e5821f81b356bc40adb63f8b0914940
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.Windsor
17 using System;
18 using System.Collections;
20 using Castle.Core;
21 using Castle.MicroKernel;
22 using Castle.Windsor.Configuration;
23 using Castle.Windsor.Configuration.Interpreters;
25 /// <summary>
26 /// Implementation of <see cref="IWindsorContainer"/>
27 /// which delegates to <see cref="IKernel"/> implementation.
28 /// </summary>
29 [Serializable]
30 public class WindsorContainer : MarshalByRefObject, IWindsorContainer
32 #region Fields
34 private readonly string name = Guid.NewGuid().ToString();
35 private readonly IDictionary childContainers = Hashtable.Synchronized(new Hashtable());
37 private IKernel kernel;
38 private IWindsorContainer parent;
39 private IComponentsInstaller installer;
41 #endregion
43 #region Constructors
45 /// <summary>
46 /// Constructs a container without any external
47 /// configuration reference
48 /// </summary>
49 public WindsorContainer() : this(new DefaultKernel(), new Installer.DefaultComponentInstaller())
53 /// <summary>
54 /// Constructs a container using the specified
55 /// <see cref="IConfigurationStore"/> implementation.
56 /// </summary>
57 /// <param name="store">The instance of an <see cref="IConfigurationStore"/> implementation.</param>
58 public WindsorContainer(IConfigurationStore store) : this()
60 kernel.ConfigurationStore = store;
62 RunInstaller();
65 /// <summary>
66 /// Constructs a container using the specified
67 /// <see cref="IConfigurationInterpreter"/> implementation.
68 /// </summary>
69 /// <param name="interpreter">The instance of an <see cref="IConfigurationInterpreter"/> implementation.</param>
70 public WindsorContainer(IConfigurationInterpreter interpreter) : this()
72 if (interpreter == null) throw new ArgumentNullException("interpreter");
74 interpreter.ProcessResource(interpreter.Source, kernel.ConfigurationStore);
76 RunInstaller();
79 /// <summary>
80 /// Initializes a new instance of the <see cref="WindsorContainer"/> class.
81 /// </summary>
82 /// <param name="interpreter">The interpreter.</param>
83 /// <param name="environmentInfo">The environment info.</param>
84 public WindsorContainer(IConfigurationInterpreter interpreter, IEnvironmentInfo environmentInfo) : this()
86 if (interpreter == null) throw new ArgumentNullException("interpreter");
87 if (environmentInfo == null) throw new ArgumentNullException("environmentInfo");
89 interpreter.EnvironmentName = environmentInfo.GetEnvironmentName();
90 interpreter.ProcessResource(interpreter.Source, kernel.ConfigurationStore);
92 RunInstaller();
95 /// <summary>
96 /// Initializes a new instance of the <see cref="WindsorContainer"/> class using a
97 /// xml file to configure it.
98 /// <para>
99 /// Equivalent to the use of <c>new WindsorContainer(new XmlInterpreter(xmlFile))</c>
100 /// </para>
101 /// </summary>
102 /// <param name="xmlFile">The XML file.</param>
103 public WindsorContainer(String xmlFile) : this(new XmlInterpreter(xmlFile))
107 /// <summary>
108 /// Constructs a container using the specified <see cref="IKernel"/>
109 /// implementation. Rarely used.
110 /// </summary>
111 /// <remarks>
112 /// This constructs sets the Kernel.ProxyFactory property to
113 /// <see cref="Proxy.DefaultProxyFactory"/>
114 /// </remarks>
115 /// <param name="kernel">Kernel instance</param>
116 /// <param name="installer">Installer instance</param>
117 public WindsorContainer(IKernel kernel, IComponentsInstaller installer) : this(Guid.NewGuid().ToString(), kernel, installer)
121 /// <summary>
122 /// Constructs a container using the specified <see cref="IKernel"/>
123 /// implementation. Rarely used.
124 /// </summary>
125 /// <remarks>
126 /// This constructs sets the Kernel.ProxyFactory property to
127 /// <see cref="Proxy.DefaultProxyFactory"/>
128 /// </remarks>
129 /// <param name="name">Container's name</param>
130 /// <param name="kernel">Kernel instance</param>
131 /// <param name="installer">Installer instance</param>
132 public WindsorContainer(String name, IKernel kernel, IComponentsInstaller installer)
134 if (name == null) throw new ArgumentNullException("name");
135 if (kernel == null) throw new ArgumentNullException("kernel");
136 if (installer == null) throw new ArgumentNullException("installer");
138 this.name = name;
139 this.kernel = kernel;
140 this.kernel.ProxyFactory = new Proxy.DefaultProxyFactory();
141 this.installer = installer;
144 /// <summary>
145 /// Constructs with a given <see cref="IProxyFactory"/>.
146 /// </summary>
147 /// <param name="proxyFactory">A instance of an <see cref="IProxyFactory"/>.</param>
148 public WindsorContainer(IProxyFactory proxyFactory)
150 if (proxyFactory == null) throw new ArgumentNullException("proxyFactory");
152 kernel = new DefaultKernel(proxyFactory);
154 installer = new Installer.DefaultComponentInstaller();
157 /// <summary>
158 /// Constructs a container assigning a parent container
159 /// before starting the dependency resolution.
160 /// </summary>
161 /// <param name="parent">The instance of an <see cref="IWindsorContainer"/></param>
162 /// <param name="interpreter">The instance of an <see cref="IConfigurationInterpreter"/> implementation</param>
163 public WindsorContainer(IWindsorContainer parent, IConfigurationInterpreter interpreter) : this()
165 if (parent == null) throw new ArgumentNullException("parent");
166 if (interpreter == null) throw new ArgumentNullException("interpreter");
168 parent.AddChildContainer(this);
170 interpreter.ProcessResource(interpreter.Source, kernel.ConfigurationStore);
172 RunInstaller();
175 /// <summary>
176 /// Initializes a new instance of the <see cref="WindsorContainer"/> class.
177 /// </summary>
178 /// <param name="name">The container's name.</param>
179 /// <param name="parent">The parent.</param>
180 /// <param name="interpreter">The interpreter.</param>
181 public WindsorContainer(string name, IWindsorContainer parent, IConfigurationInterpreter interpreter) : this()
183 if (name == null) throw new ArgumentNullException("name");
184 if (parent == null) throw new ArgumentNullException("parent");
185 if (interpreter == null) throw new ArgumentNullException("interpreter");
187 this.name = name;
189 parent.AddChildContainer(this);
191 interpreter.ProcessResource(interpreter.Source, kernel.ConfigurationStore);
193 RunInstaller();
196 #endregion
198 #region IWindsorContainer Members
200 /// <summary>
201 /// Gets the container's name
202 /// </summary>
203 /// <remarks>
204 /// Only useful when child containers are being used
205 /// </remarks>
206 /// <value>The container's name.</value>
207 public string Name
209 get { return name; }
212 /// <summary>
213 /// Returns the inner instance of the MicroKernel
214 /// </summary>
215 public virtual IKernel Kernel
217 get { return kernel; }
220 /// <summary>
221 /// Gets or sets the parent container if this instance
222 /// is a sub container.
223 /// </summary>
224 public virtual IWindsorContainer Parent
226 get { return parent; }
229 if( value == null )
231 if (parent != null)
233 parent.RemoveChildContainer(this);
234 parent = null;
237 else
239 if (value != parent)
241 parent = value;
242 parent.AddChildContainer(this);
248 /// <summary>
249 /// Registers a facility within the kernel.
250 /// </summary>
251 /// <param name="key"></param>
252 /// <param name="facility"></param>
253 public virtual void AddFacility(String key, IFacility facility)
255 kernel.AddFacility(key, facility);
258 /// <summary>
259 /// Adds a component to be managed by the container
260 /// </summary>
261 /// <param name="key"></param>
262 /// <param name="classType"></param>
263 public virtual void AddComponent(String key, Type classType)
265 kernel.AddComponent(key, classType);
268 /// <summary>
269 /// Adds a component to be managed by the container
270 /// </summary>
271 /// <param name="key"></param>
272 /// <param name="serviceType"></param>
273 /// <param name="classType"></param>
274 public virtual void AddComponent(String key, Type serviceType, Type classType)
276 kernel.AddComponent(key, serviceType, classType);
279 /// <summary>
280 /// Adds a component to be managed by the container
281 /// </summary>
282 /// <param name="key">The key by which the component gets indexed.</param>
283 /// <param name="classType">The <see cref="Type"/> to manage.</param>
284 /// <param name="lifestyle">The <see cref="LifestyleType"/> with which to manage the component.</param>
285 public void AddComponentWithLifestyle(string key, Type classType, LifestyleType lifestyle)
287 kernel.AddComponent(key, classType, lifestyle, true);
290 /// <summary>
291 /// Adds a component to be managed by the container
292 /// </summary>
293 /// <param name="key">The key by which the component gets indexed.</param>
294 /// <param name="serviceType">The service <see cref="Type"/> that the component implements.</param>
295 /// <param name="classType">The <see cref="Type"/> to manage.</param>
296 /// <param name="lifestyle">The <see cref="LifestyleType"/> with which to manage the component.</param>
297 public void AddComponentWithLifestyle(string key, Type serviceType, Type classType, LifestyleType lifestyle)
299 kernel.AddComponent(key, serviceType, classType, lifestyle, true);
302 public virtual void AddComponentWithProperties(string key, Type classType, IDictionary extendedProperties)
304 kernel.AddComponentWithExtendedProperties(key, classType, extendedProperties);
307 public virtual void AddComponentWithProperties(string key, Type serviceType, Type classType,
308 IDictionary extendedProperties)
310 kernel.AddComponentWithExtendedProperties(key, serviceType, classType, extendedProperties);
313 /// <summary>
314 /// Adds a component to be managed by the container.
315 /// The key to obtain the component will be the FullName of the type.
316 /// </summary>
317 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
318 public void AddComponent<T>()
320 Type t = typeof(T);
321 AddComponent(t.FullName, t);
324 /// <summary>
325 /// Adds a component to be managed by the container
326 /// </summary>
327 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
328 /// <param name="key">The key by which the component gets indexed.</param>
329 public void AddComponent<T>(string key)
331 AddComponent(key, typeof(T));
334 /// <summary>
335 /// Adds a component to be managed by the container.
336 /// The key to obtain the component will be the FullName of the type.
337 /// </summary>
338 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
339 /// <param name="lifestyle">The <see cref="LifestyleType"/> with which to manage the component.</param>
340 public void AddComponentWithLifestyle<T>(LifestyleType lifestyle)
342 Type t = typeof(T);
343 AddComponentWithLifestyle(t.FullName, t, lifestyle);
346 /// <summary>
347 /// Adds a component to be managed by the container
348 /// </summary>
349 /// <typeparam name="I">The service <see cref="Type"/> that the component implements.</typeparam>
350 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
351 /// <param name="key">The key by which the component gets indexed.</param>
352 public void AddComponent<I, T>(string key) where T : class
354 AddComponent(key, typeof(I), typeof(T));
357 /// <summary>
358 /// Adds a component to be managed by the container
359 /// The key to obtain the component will be the FullName of the type.
360 /// </summary>
361 /// <typeparam name="I">The service <see cref="Type"/> that the component implements.</typeparam>
362 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
363 /// <param name="lifestyle">The <see cref="LifestyleType"/> with which to manage the component.</param>
364 public void AddComponentWithLifestyle<I, T>(LifestyleType lifestyle) where T : class
366 Type t = typeof(T);
367 AddComponentWithLifestyle(t.FullName, typeof(I), t, lifestyle);
370 /// <summary>
371 /// Adds a component to be managed by the container
372 /// </summary>
373 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
374 /// <param name="key">The key by which the component gets indexed.</param>
375 /// <param name="lifestyle">The <see cref="LifestyleType"/> with which to manage the component.</param>
376 public void AddComponentWithLifestyle<T>(string key, LifestyleType lifestyle)
378 AddComponentWithLifestyle(key, typeof(T), lifestyle);
381 /// <summary>
382 /// Adds a component to be managed by the container
383 /// The key to obtain the component will be the FullName of the type.
384 /// </summary>
385 /// <typeparam name="I">The service <see cref="Type"/> that the component implements.</typeparam>
386 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
387 public void AddComponent<I, T>() where T : class
389 Type t = typeof(T);
390 AddComponent(t.FullName, typeof(I), t);
393 /// <summary>
394 /// Adds a component to be managed by the container
395 /// </summary>
396 /// <typeparam name="I">The service <see cref="Type"/> that the component implements.</typeparam>
397 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
398 /// <param name="key">The key by which the component gets indexed.</param>
399 /// <param name="lifestyle">The <see cref="LifestyleType"/> with which to manage the component.</param>
400 public void AddComponentWithLifestyle<I, T>(string key, LifestyleType lifestyle) where T : class
402 AddComponentWithLifestyle(key, typeof(I), typeof(T), lifestyle);
405 /// <summary>
406 /// Adds a concrete class as a component and specify the extended properties.
407 /// Used by facilities, mostly.
408 /// The key to obtain the component will be the FullName of the type.
409 /// </summary>
410 /// <typeparam name="T"></typeparam>
411 /// <param name="extendedProperties"></param>
412 public void AddComponentWithProperties<T>(IDictionary extendedProperties)
414 Type t = typeof(T);
415 AddComponentWithProperties(t.FullName, t, extendedProperties);
418 /// <summary>
419 /// Adds a concrete class as a component and specify the extended properties.
420 /// Used by facilities, mostly.
421 /// </summary>
422 /// <typeparam name="T"></typeparam>
423 /// <param name="key"></param>
424 /// <param name="extendedProperties"></param>
425 public void AddComponentWithProperties<T>(string key, IDictionary extendedProperties)
427 AddComponentWithProperties(key, typeof(T), extendedProperties);
430 /// <summary>
431 /// Adds a concrete class and an interface
432 /// as a component and specify the extended properties.
433 /// Used by facilities, mostly.
434 /// The key to obtain the component will be the FullName of the type.
435 /// </summary>
436 /// <typeparam name="I"></typeparam>
437 /// <typeparam name="T"></typeparam>
438 /// <param name="extendedProperties"></param>
439 public void AddComponentWithLifestyle<I, T>(IDictionary extendedProperties) where T : class
441 Type t = typeof(T);
442 AddComponentWithProperties(t.FullName, typeof(I), t, extendedProperties);
445 /// <summary>
446 /// Adds a concrete class and an interface
447 /// as a component and specify the extended properties.
448 /// Used by facilities, mostly.
449 /// </summary>
450 /// <typeparam name="I"></typeparam>
451 /// <typeparam name="T"></typeparam>
452 /// <param name="key"></param>
453 /// <param name="extendedProperties"></param>
454 public void AddComponentWithLifestyle<I, T>(string key, IDictionary extendedProperties) where T : class
456 AddComponentWithProperties(key, typeof(I), typeof(T), extendedProperties);
459 /// <summary>
460 /// Returns a component instance by the key
461 /// </summary>
462 /// <param name="key"></param>
463 /// <returns></returns>
464 public virtual object Resolve(String key)
466 return kernel[key];
469 /// <summary>
470 /// Returns a component instance by the service
471 /// </summary>
472 /// <param name="service"></param>
473 /// <param name="arguments"></param>
474 /// <returns></returns>
475 public virtual object Resolve(Type service, IDictionary arguments)
477 return kernel.Resolve(service, arguments);
480 /// <summary>
481 /// Returns a component instance by the key
482 /// </summary>
483 /// <param name="key"></param>
484 /// <param name="arguments"></param>
485 /// <returns></returns>
486 public virtual object Resolve(String key, IDictionary arguments)
488 return kernel.Resolve(key, arguments);
491 /// <summary>
492 /// Returns a component instance by the service
493 /// </summary>
494 /// <param name="service"></param>
495 /// <returns></returns>
496 public virtual object Resolve(Type service)
498 return kernel[service];
501 /// <summary>
502 /// Shortcut to the method <see cref="Resolve(String)"/>
503 /// </summary>
504 public virtual object this[String key]
506 get { return Resolve(key); }
509 /// <summary>
510 /// Shortcut to the method <see cref="Resolve(Type)"/>
511 /// </summary>
512 public virtual object this[Type service]
514 get { return Resolve(service); }
517 /// <summary>
518 /// Returns a component instance by the key
519 /// </summary>
520 /// <param name="key"></param>
521 /// <param name="service"></param>
522 /// <returns></returns>
523 public virtual object Resolve(String key, Type service)
525 return kernel.Resolve(key, service);
528 /// <summary>
529 ///
530 /// </summary>
531 /// <param name="key"></param>
532 /// <param name="service"></param>
533 /// <param name="arguments"></param>
534 /// <returns></returns>
535 public virtual object Resolve(String key, Type service, IDictionary arguments)
537 return kernel.Resolve(key, service, arguments);
540 /// <summary>
541 /// Returns a component instance by the service
542 /// </summary>
543 /// <typeparam name="T"></typeparam>
544 /// <param name="arguments"></param>
545 /// <returns></returns>
546 public T Resolve<T>(IDictionary arguments)
548 return (T) Resolve(typeof(T), arguments);
551 /// <summary>
552 /// Returns a component instance by the key
553 /// </summary>
554 /// <param name="key"></param>
555 /// <param name="arguments"></param>
556 /// <returns></returns>
557 public virtual T Resolve<T>(String key, IDictionary arguments)
559 return (T) Resolve(key, typeof(T), arguments);
562 /// <summary>
563 /// Returns a component instance by the service
564 /// </summary>
565 /// <typeparam name="T"></typeparam>
566 /// <returns></returns>
567 public T Resolve<T>()
569 return (T)Resolve(typeof(T));
572 /// <summary>
573 /// Returns a component instance by the key
574 /// </summary>
575 /// <param name="key"></param>
576 /// <returns></returns>
577 public virtual T Resolve<T>(String key)
579 return (T)Resolve(key, typeof(T));
582 /// <summary>
583 /// Releases a component instance
584 /// </summary>
585 /// <param name="instance"></param>
586 public virtual void Release(object instance)
588 kernel.ReleaseComponent(instance);
591 /// <summary>
592 /// Registers a subcontainer. The components exposed
593 /// by this container will be accessible from subcontainers.
594 /// </summary>
595 /// <param name="childContainer"></param>
596 public virtual void AddChildContainer(IWindsorContainer childContainer)
598 if (childContainer == null) throw new ArgumentNullException("childContainer");
600 if (!childContainers.Contains(childContainer.Name))
602 lock (childContainers.SyncRoot)
604 if (!childContainers.Contains(childContainer.Name))
606 kernel.AddChildKernel(childContainer.Kernel);
607 childContainers.Add(childContainer.Name, childContainer);
608 childContainer.Parent = this;
614 /// <summary>
615 /// Removes (unregisters) a subcontainer. The components exposed by this container
616 /// will no longer be accessible to the child container.
617 /// </summary>
618 /// <param name="childContainer"></param>
619 public virtual void RemoveChildContainer(IWindsorContainer childContainer)
621 if (childContainer == null) throw new ArgumentNullException("childContainer");
623 if (childContainers.Contains(childContainer.Name))
625 lock (childContainers.SyncRoot)
627 if (childContainers.Contains(childContainer.Name))
629 kernel.RemoveChildKernel(childContainer.Kernel);
630 childContainers.Remove(childContainer.Name);
631 childContainer.Parent = null;
637 /// <summary>
638 /// Gets a child container instance by name.
639 /// </summary>
640 /// <param name="name">The container's name.</param>
641 /// <returns>The child container instance or null</returns>
642 public IWindsorContainer GetChildContainer(string name)
644 return childContainers[name] as IWindsorContainer;
647 #endregion
649 #region IServiceProviderEx Members
651 /// <summary>
652 /// Gets the service object of the specified type.
653 /// </summary>
654 /// <returns>
655 /// A service object of type serviceType.
656 /// </returns>
657 /// <param name="serviceType">An object that specifies the type of service object to get. </param>
658 public object GetService(Type serviceType)
660 return kernel.Resolve(serviceType);
663 /// <summary>
664 /// Gets the service object of the specified type.
665 /// </summary>
666 /// <returns>
667 /// A service object of type serviceType.
668 /// </returns>
669 public T GetService<T>()
671 Type serviceType = typeof(T);
672 return (T) kernel.Resolve(serviceType);
675 #endregion
677 #region IDisposable Members
679 /// <summary>
680 /// Executes Dispose on underlying <see cref="IKernel"/>
681 /// </summary>
682 public virtual void Dispose()
684 Parent = null;
685 childContainers.Clear();
686 kernel.Dispose();
689 #endregion
691 #region Protected Operations Members
693 public IComponentsInstaller Installer
695 get { return installer; }
698 protected virtual void RunInstaller()
700 if (installer != null)
702 installer.SetUp(this, kernel.ConfigurationStore);
706 #endregion