2008-04-16 Marek Habersack <mhabersack@novell.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
40 #if NET_2_0
41         public class ServiceContainer : IServiceContainer, IServiceProvider, IDisposable
42 #else
43         public sealed class ServiceContainer : IServiceContainer, IServiceProvider
44 #endif
45         {
46
47                 private IServiceProvider parentProvider;
48                 private Hashtable services = new Hashtable ();
49 #if NET_2_0
50                 private bool _disposed = false;
51 #endif
52                 
53                 public ServiceContainer()
54                         : this (null)
55                 {
56                 }
57
58                 public ServiceContainer (IServiceProvider parentProvider)
59                 {
60                         this.parentProvider = parentProvider;
61                 }
62
63                 public void AddService (Type serviceType, object serviceInstance)
64                 {
65                         AddService (serviceType, serviceInstance, false);
66                 }
67
68                 public void AddService (Type serviceType, ServiceCreatorCallback callback)
69                 {
70                         AddService (serviceType, callback, false);
71                 }
72
73 #if NET_2_0
74                 public virtual
75 #else
76                 public
77 #endif
78                 void AddService (Type serviceType, 
79                                         object serviceInstance,
80                                         bool promote)
81                 {
82                         if (serviceType == null)
83                                 throw new ArgumentNullException ("serviceType", "Cannot be null");
84                         if (promote)
85                                 if (parentProvider != null)
86                                         ((IServiceContainer)parentProvider.GetService(typeof(IServiceContainer))).AddService (serviceType, serviceInstance, promote);
87                         if (services.Contains (serviceType)) {
88                                         throw new ArgumentException (string.Format ("The service {0} already exists in the service container.", serviceType.ToString()));
89                         }
90                         services.Add (serviceType, serviceInstance);
91                 }
92
93 #if NET_2_0
94                 public virtual
95 #else
96                 public
97 #endif
98                 void AddService (Type serviceType,
99                                         ServiceCreatorCallback callback,
100                                         bool promote)
101                 {
102                         if (serviceType == null)
103                                 throw new ArgumentNullException ("serviceType", "Cannot be null");
104                         if (promote)
105                                 if (parentProvider != null)
106                                         ((IServiceContainer)parentProvider.GetService(typeof(IServiceContainer))).AddService (serviceType, callback, promote);
107                         if (services.Contains (serviceType)) {
108                                         throw new ArgumentException (string.Format ("The service {0} already exists in the service container.", serviceType.ToString()));
109                         }
110                         services.Add (serviceType, callback);
111                 }
112
113                 public void RemoveService (Type serviceType)
114                 {
115                         RemoveService (serviceType, false);
116                 }
117         
118 #if NET_2_0
119                 public virtual void RemoveService (Type serviceType, bool promote)
120 #else
121         public void RemoveService (Type serviceType, bool promote)
122 #endif
123                 {
124                         if (serviceType == null)
125                                 throw new ArgumentNullException ("serviceType", "Cannot be null");
126                         if (promote)
127                                 if (parentProvider != null)
128                                         ((IServiceContainer)parentProvider.GetService(typeof(IServiceContainer))).RemoveService (serviceType, promote);
129                         else
130                                 services.Remove (serviceType);
131                 }
132
133 #if NET_2_0
134                 public virtual
135 #else
136                 public
137 #endif
138                 object GetService (Type serviceType)
139                 {
140 #if NET_2_0
141                         object result = null;
142                         Type[] defaultServices = this.DefaultServices;
143                         for (int i=0; i < defaultServices.Length; i++) {
144                                 if (defaultServices[i] == serviceType) {
145                                         result = this;
146                                         break;
147                                 }
148                         }
149                         if (result == null)
150                                 result = services[serviceType];
151 #else
152                         object result = services[serviceType];
153 #endif
154                         if (result == null && parentProvider != null)
155                                 result = parentProvider.GetService (serviceType);
156                         if (result != null) {
157                                 ServiceCreatorCallback  cb = result as ServiceCreatorCallback;
158                                 if (cb != null) {
159                                         result = cb (this, serviceType);
160                                         services[serviceType] = result;
161                                 }
162                                 
163                         }
164                         return result;
165                 }
166
167 #if NET_2_0
168                 protected virtual Type [] DefaultServices {
169                         get { return new Type [] { typeof (IServiceContainer), typeof (ServiceContainer)}; }
170                 }
171
172                 public void Dispose ()
173                 {
174                         this.Dispose (true);
175                         GC.SuppressFinalize(this);
176                 }
177
178                 protected virtual void Dispose (bool disposing)
179                 {
180                         if (!_disposed) {
181                                 if (disposing) {
182                                         if (this.services != null) {
183                                                 foreach (object obj in this.services) {
184                                                         if (obj is IDisposable) {
185                                                                 ((IDisposable) obj).Dispose ();
186                                                         }
187                                                 }
188                                                 this.services = null;
189                                         }
190                                 }
191                                 _disposed = true;
192                         }
193                 }
194 #endif
195                 
196         }
197 }