2008-10-21 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / System / System.ComponentModel.Design / ServiceContainer.cs
1 //
2 // System.ComponentModel.Design.ServiceContainer.cs
3 //
4 // Authors:
5 //   Martin Willemoes Hansen (mwh@sysrq.dk)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //   Ivan N. Zlatev (contact i-nZ.net)
8 //
9 // (C) 2003 Martin Willemoes Hansen
10 // (C) 2003 Andreas Nahr
11 // (C) 2006 Ivan N. Zlatev
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Collections;
36
37 namespace System.ComponentModel.Design
38 {
39 #if NET_2_0
40         public class ServiceContainer : IServiceContainer, IServiceProvider, IDisposable
41 #else
42         public sealed class ServiceContainer : IServiceContainer, IServiceProvider
43 #endif
44         {
45                 private IServiceProvider parentProvider;
46                 private Hashtable services;
47 #if NET_2_0
48                 private bool _disposed;
49 #endif
50                 
51                 public ServiceContainer()
52                         : this (null)
53                 {
54                 }
55
56                 private Hashtable Services {
57                         get {
58                                 if (services == null)
59                                         services = new Hashtable ();
60                                 return services;
61                         }
62                 }
63
64                 public ServiceContainer (IServiceProvider parentProvider)
65                 {
66                         this.parentProvider = parentProvider;
67                 }
68
69                 public void AddService (Type serviceType, object serviceInstance)
70                 {
71                         AddService (serviceType, serviceInstance, false);
72                 }
73
74                 public void AddService (Type serviceType, ServiceCreatorCallback callback)
75                 {
76                         AddService (serviceType, callback, false);
77                 }
78
79 #if NET_2_0
80                 public virtual
81 #else
82                 public
83 #endif
84                 void AddService (Type serviceType,
85                                         object serviceInstance,
86                                         bool promote)
87                 {
88                         if (promote && parentProvider != null) {
89                                 IServiceContainer container = (IServiceContainer)
90                                         parentProvider.GetService (typeof (IServiceContainer));
91                                 container.AddService (serviceType, serviceInstance, promote);
92                                 return;
93                         }
94
95                         if (serviceType == null)
96                                 throw new ArgumentNullException ("serviceType");
97                         if (serviceInstance == null)
98                                 throw new ArgumentNullException ("serviceInstance");
99                         if (Services.Contains (serviceType))
100                                 throw new ArgumentException (string.Format (
101                                         "The service {0} already exists in the service container.",
102                                         serviceType.ToString ()), "serviceType");
103                         Services.Add (serviceType, serviceInstance);
104                 }
105
106 #if NET_2_0
107                 public virtual
108 #else
109                 public
110 #endif
111                 void AddService (Type serviceType,
112                                         ServiceCreatorCallback callback,
113                                         bool promote)
114                 {
115                         if (promote && parentProvider != null) {
116                                 IServiceContainer container = (IServiceContainer)
117                                         parentProvider.GetService (typeof (IServiceContainer));
118                                 container.AddService (serviceType, callback, promote);
119                                 return;
120                         }
121
122                         if (serviceType == null)
123                                 throw new ArgumentNullException ("serviceType");
124                         if (callback == null)
125                                 throw new ArgumentNullException ("callback");
126                         if (Services.Contains (serviceType))
127                                 throw new ArgumentException (string.Format (
128                                         "The service {0} already exists in the service container.",
129                                         serviceType.ToString ()), "serviceType");
130                         Services.Add (serviceType, callback);
131                 }
132
133                 public void RemoveService (Type serviceType)
134                 {
135                         RemoveService (serviceType, false);
136                 }
137
138 #if NET_2_0
139                 public virtual void RemoveService (Type serviceType, bool promote)
140 #else
141                 public void RemoveService (Type serviceType, bool promote)
142 #endif
143                 {
144                         if (promote && parentProvider != null) {
145                                 IServiceContainer container = (IServiceContainer)
146                                         parentProvider.GetService (typeof (IServiceContainer));
147                                 container.RemoveService (serviceType, promote);
148                                 return;
149                         }
150
151                         if (serviceType == null)
152                                 throw new ArgumentNullException ("serviceType");
153                         Services.Remove (serviceType);
154                 }
155
156 #if NET_2_0
157                 public virtual
158 #else
159                 public
160 #endif
161                 object GetService (Type serviceType)
162                 {
163                         object result = null;
164
165                         Type[] defaultServices = this.DefaultServices;
166                         for (int i=0; i < defaultServices.Length; i++) {
167                                 if (defaultServices[i] == serviceType) {
168                                         result = this;
169                                         break;
170                                 }
171                         }
172
173                         if (result == null)
174                                 result = Services [serviceType];
175                         if (result == null && parentProvider != null)
176                                 result = parentProvider.GetService (serviceType);
177                         if (result != null) {
178                                 ServiceCreatorCallback cb = result as ServiceCreatorCallback;
179                                 if (cb != null) {
180                                         result = cb (this, serviceType);
181                                         Services [serviceType] = result;
182                                 }
183                         }
184                         return result;
185                 }
186
187 #if NET_2_0
188                 protected virtual
189 #endif
190                 Type [] DefaultServices {
191                         get {
192 #if NET_2_0
193                                 return new Type [] { typeof (IServiceContainer), typeof (ServiceContainer)};
194 #else
195                                 return new Type [] { typeof (IServiceContainer) };
196 #endif
197                         }
198                 }
199
200 #if NET_2_0
201                 public void Dispose ()
202                 {
203                         this.Dispose (true);
204                         GC.SuppressFinalize (this);
205                 }
206
207                 protected virtual void Dispose (bool disposing)
208                 {
209                         if (!_disposed) {
210                                 if (disposing) {
211                                         if (services != null) {
212                                                 foreach (object obj in services) {
213                                                         if (obj is IDisposable) {
214                                                                 ((IDisposable) obj).Dispose ();
215                                                         }
216                                                 }
217                                                 services = null;
218                                         }
219                                 }
220                                 _disposed = true;
221                         }
222                 }
223 #endif
224         }
225 }