1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
18 using System
.Collections
;
21 using Castle
.MicroKernel
;
22 using Castle
.Windsor
.Configuration
;
23 using Castle
.Windsor
.Configuration
.Interpreters
;
26 /// Implementation of <see cref="IWindsorContainer"/>
27 /// which delegates to <see cref="IKernel"/> implementation.
30 public class WindsorContainer
: MarshalByRefObject
, IWindsorContainer
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
;
46 /// Constructs a container without any external
47 /// configuration reference
49 public WindsorContainer() : this(new DefaultKernel(), new Installer
.DefaultComponentInstaller())
54 /// Constructs a container using the specified
55 /// <see cref="IConfigurationStore"/> implementation.
57 /// <param name="store">The instance of an <see cref="IConfigurationStore"/> implementation.</param>
58 public WindsorContainer(IConfigurationStore store
) : this()
60 kernel
.ConfigurationStore
= store
;
66 /// Constructs a container using the specified
67 /// <see cref="IConfigurationInterpreter"/> implementation.
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
);
80 /// Initializes a new instance of the <see cref="WindsorContainer"/> class.
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
);
96 /// Initializes a new instance of the <see cref="WindsorContainer"/> class using a
97 /// xml file to configure it.
99 /// Equivalent to the use of <c>new WindsorContainer(new XmlInterpreter(xmlFile))</c>
102 /// <param name="xmlFile">The XML file.</param>
103 public WindsorContainer(String xmlFile
) : this(new XmlInterpreter(xmlFile
))
108 /// Constructs a container using the specified <see cref="IKernel"/>
109 /// implementation. Rarely used.
112 /// This constructs sets the Kernel.ProxyFactory property to
113 /// <see cref="Proxy.DefaultProxyFactory"/>
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
)
122 /// Constructs a container using the specified <see cref="IKernel"/>
123 /// implementation. Rarely used.
126 /// This constructs sets the Kernel.ProxyFactory property to
127 /// <see cref="Proxy.DefaultProxyFactory"/>
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");
139 this.kernel
= kernel
;
140 this.kernel
.ProxyFactory
= new Proxy
.DefaultProxyFactory();
141 this.installer
= installer
;
145 /// Constructs with a given <see cref="IProxyFactory"/>.
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();
158 /// Constructs a container assigning a parent container
159 /// before starting the dependency resolution.
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
);
176 /// Initializes a new instance of the <see cref="WindsorContainer"/> class.
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");
189 parent
.AddChildContainer(this);
191 interpreter
.ProcessResource(interpreter
.Source
, kernel
.ConfigurationStore
);
198 #region IWindsorContainer Members
201 /// Gets the container's name
204 /// Only useful when child containers are being used
206 /// <value>The container's name.</value>
213 /// Returns the inner instance of the MicroKernel
215 public virtual IKernel Kernel
217 get { return kernel; }
221 /// Gets or sets the parent container if this instance
222 /// is a sub container.
224 public virtual IWindsorContainer Parent
226 get { return parent; }
233 parent
.RemoveChildContainer(this);
242 parent
.AddChildContainer(this);
249 /// Registers a facility within the kernel.
251 /// <param name="key"></param>
252 /// <param name="facility"></param>
253 public virtual void AddFacility(String key
, IFacility facility
)
255 kernel
.AddFacility(key
, facility
);
259 /// Adds a component to be managed by the container
261 /// <param name="key"></param>
262 /// <param name="classType"></param>
263 public virtual void AddComponent(String key
, Type classType
)
265 kernel
.AddComponent(key
, classType
);
269 /// Adds a component to be managed by the container
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
);
280 /// Adds a component to be managed by the container
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);
291 /// Adds a component to be managed by the container
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
);
314 /// Adds a component to be managed by the container.
315 /// The key to obtain the component will be the FullName of the type.
317 /// <typeparam name="T">The <see cref="Type"/> to manage.</typeparam>
318 public void AddComponent
<T
>()
321 AddComponent(t
.FullName
, t
);
325 /// Adds a component to be managed by the container
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
));
335 /// Adds a component to be managed by the container.
336 /// The key to obtain the component will be the FullName of the type.
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
)
343 AddComponentWithLifestyle(t
.FullName
, t
, lifestyle
);
347 /// Adds a component to be managed by the container
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
));
358 /// Adds a component to be managed by the container
359 /// The key to obtain the component will be the FullName of the type.
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
367 AddComponentWithLifestyle(t
.FullName
, typeof(I
), t
, lifestyle
);
371 /// Adds a component to be managed by the container
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
);
382 /// Adds a component to be managed by the container
383 /// The key to obtain the component will be the FullName of the type.
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
390 AddComponent(t
.FullName
, typeof(I
), t
);
394 /// Adds a component to be managed by the container
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
);
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.
410 /// <typeparam name="T"></typeparam>
411 /// <param name="extendedProperties"></param>
412 public void AddComponentWithProperties
<T
>(IDictionary extendedProperties
)
415 AddComponentWithProperties(t
.FullName
, t
, extendedProperties
);
419 /// Adds a concrete class as a component and specify the extended properties.
420 /// Used by facilities, mostly.
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
);
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.
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
442 AddComponentWithProperties(t
.FullName
, typeof(I
), t
, extendedProperties
);
446 /// Adds a concrete class and an interface
447 /// as a component and specify the extended properties.
448 /// Used by facilities, mostly.
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
);
460 /// Returns a component instance by the key
462 /// <param name="key"></param>
463 /// <returns></returns>
464 public virtual object Resolve(String key
)
470 /// Returns a component instance by the service
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
);
481 /// Returns a component instance by the key
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
);
492 /// Returns a component instance by the service
494 /// <param name="service"></param>
495 /// <returns></returns>
496 public virtual object Resolve(Type service
)
498 return kernel
[service
];
502 /// Shortcut to the method <see cref="Resolve(String)"/>
504 public virtual object this[String key
]
506 get { return Resolve(key); }
510 /// Shortcut to the method <see cref="Resolve(Type)"/>
512 public virtual object this[Type service
]
514 get { return Resolve(service); }
518 /// Returns a component instance by the key
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
);
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
);
541 /// Returns a component instance by the service
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
);
552 /// Returns a component instance by the key
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
);
563 /// Returns a component instance by the service
565 /// <typeparam name="T"></typeparam>
566 /// <returns></returns>
567 public T Resolve
<T
>()
569 return (T
)Resolve(typeof(T
));
573 /// Returns a component instance by the key
575 /// <param name="key"></param>
576 /// <returns></returns>
577 public virtual T Resolve
<T
>(String key
)
579 return (T
)Resolve(key
, typeof(T
));
583 /// Releases a component instance
585 /// <param name="instance"></param>
586 public virtual void Release(object instance
)
588 kernel
.ReleaseComponent(instance
);
592 /// Registers a subcontainer. The components exposed
593 /// by this container will be accessible from subcontainers.
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;
615 /// Removes (unregisters) a subcontainer. The components exposed by this container
616 /// will no longer be accessible to the child container.
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;
638 /// Gets a child container instance by name.
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
;
649 #region IServiceProviderEx Members
652 /// Gets the service object of the specified type.
655 /// A service object of type serviceType.
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
);
664 /// Gets the service object of the specified type.
667 /// A service object of type serviceType.
669 public T GetService
<T
>()
671 Type serviceType
= typeof(T
);
672 return (T
) kernel
.Resolve(serviceType
);
677 #region IDisposable Members
680 /// Executes Dispose on underlying <see cref="IKernel"/>
682 public virtual void Dispose()
685 childContainers
.Clear();
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
);