Relaxed the need for Types that represent database boundaries to extend from ActiveRe...
[castle.git] / InversionOfControl / Castle.Windsor / WindsorContainer.cs
blob86e7058d6a3698e97d8facfae502c769758725be
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 : I
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 : I
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 : I
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 : I
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 : I
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 : I
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 #if DOTNET2
519 /// <summary>
520 /// Returns a component instance by the key
521 /// </summary>
522 /// <param name="key"></param>
523 /// <param name="service"></param>
524 /// <returns></returns>
525 public virtual object Resolve(String key, Type service)
527 return kernel.Resolve(key, service);
530 /// <summary>
531 ///
532 /// </summary>
533 /// <param name="key"></param>
534 /// <param name="service"></param>
535 /// <param name="arguments"></param>
536 /// <returns></returns>
537 public virtual object Resolve(String key, Type service, IDictionary arguments)
539 return kernel.Resolve(key, service, arguments);
542 /// <summary>
543 /// Returns a component instance by the service
544 /// </summary>
545 /// <typeparam name="T"></typeparam>
546 /// <param name="arguments"></param>
547 /// <returns></returns>
548 public T Resolve<T>(IDictionary arguments)
550 return (T) Resolve(typeof(T), arguments);
553 /// <summary>
554 /// Returns a component instance by the key
555 /// </summary>
556 /// <param name="key"></param>
557 /// <param name="arguments"></param>
558 /// <returns></returns>
559 public virtual T Resolve<T>(String key, IDictionary arguments)
561 return (T) Resolve(key, typeof(T), arguments);
564 /// <summary>
565 /// Returns a component instance by the service
566 /// </summary>
567 /// <typeparam name="T"></typeparam>
568 /// <returns></returns>
569 public T Resolve<T>()
571 return (T)Resolve(typeof(T));
574 /// <summary>
575 /// Returns a component instance by the key
576 /// </summary>
577 /// <param name="key"></param>
578 /// <returns></returns>
579 public virtual T Resolve<T>(String key)
581 return (T)Resolve(key, typeof(T));
583 #endif
585 /// <summary>
586 /// Releases a component instance
587 /// </summary>
588 /// <param name="instance"></param>
589 public virtual void Release(object instance)
591 kernel.ReleaseComponent(instance);
594 /// <summary>
595 /// Registers a subcontainer. The components exposed
596 /// by this container will be accessible from subcontainers.
597 /// </summary>
598 /// <param name="childContainer"></param>
599 public virtual void AddChildContainer(IWindsorContainer childContainer)
601 if (childContainer == null) throw new ArgumentNullException("childContainer");
603 if (!childContainers.Contains(childContainer.Name))
605 lock (childContainers.SyncRoot)
607 if (!childContainers.Contains(childContainer.Name))
609 kernel.AddChildKernel(childContainer.Kernel);
610 childContainers.Add(childContainer.Name, childContainer);
611 childContainer.Parent = this;
617 /// <summary>
618 /// Removes (unregisters) a subcontainer. The components exposed by this container
619 /// will no longer be accessible to the child container.
620 /// </summary>
621 /// <param name="childContainer"></param>
622 public virtual void RemoveChildContainer(IWindsorContainer childContainer)
624 if (childContainer == null) throw new ArgumentNullException("childContainer");
626 if (childContainers.Contains(childContainer.Name))
628 lock (childContainers.SyncRoot)
630 if (childContainers.Contains(childContainer.Name))
632 kernel.RemoveChildKernel(childContainer.Kernel);
633 childContainers.Remove(childContainer.Name);
634 childContainer.Parent = null;
640 /// <summary>
641 /// Gets a child container instance by name.
642 /// </summary>
643 /// <param name="name">The container's name.</param>
644 /// <returns>The child container instance or null</returns>
645 public IWindsorContainer GetChildContainer(string name)
647 return childContainers[name] as IWindsorContainer;
650 #endregion
652 #region IDisposable Members
654 /// <summary>
655 /// Executes Dispose on underlying <see cref="IKernel"/>
656 /// </summary>
657 public virtual void Dispose()
659 Parent = null;
660 childContainers.Clear();
661 kernel.Dispose();
664 #endregion
666 #region Protected Operations Members
668 public IComponentsInstaller Installer
670 get { return installer; }
673 protected virtual void RunInstaller()
675 if (installer != null)
677 installer.SetUp(this, kernel.ConfigurationStore);
681 #endregion