##// END OF EJS Templates
ServiceLocator: added a cleanup callback to the service registration method
cin -
r86:b33832ab0262 v2
parent child
Show More
@@ -1,21 +1,35
1 using System;
1 using System;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Web;
5 using System.Diagnostics;
6
3
7 namespace Implab {
4 namespace Implab {
8 /// <summary>
5 /// <summary>
9 /// Коллекция сервисов, позволяет регистрировать и получать сервисы.
6 /// Коллекция сервисов, позволяет регистрировать и получать сервисы.
10 /// </summary>
7 /// </summary>
11 public class ServiceLocator: Component, IServiceLocator, IServiceProvider {
8 public class ServiceLocator: Component, IServiceLocator, IServiceProvider {
12 // запись об сервисе
9 // запись о сервисе
13 struct ServiceEntry {
10 struct ServiceEntry : IDisposable {
14 public object service; // сервис
11 public object service; // сервис
15 public bool shared; // признак того, что сервис НЕ нужно освобождать
12 public bool shared; // признак того, что сервис НЕ нужно освобождать
16 public Func<object> activator; // активатор сервиса при первом обращении
13 public Func<object> activator; // активатор сервиса при первом обращении
14 public Action<object> cleanup; // функция для очистки сервиса
17 public List<Type> associated; // ссылки на текущую запись
15 public List<Type> associated; // ссылки на текущую запись
18 public Type origin; // ссылка на оригинальную запись о сервисе
16 public Type origin; // ссылка на оригинальную запись о сервисе
17
18 #region IDisposable implementation
19
20 public void Dispose() {
21 if (shared)
22 return;
23 if (cleanup != null)
24 cleanup(service);
25 else {
26 var d = service as IDisposable;
27 if (d != null)
28 d.Dispose();
29 }
30 }
31
32 #endregion
19 }
33 }
20
34
21 // словарь существующих сервисов
35 // словарь существующих сервисов
@@ -72,8 +86,7 namespace Implab {
72 /// <param name="serviceType">Тип запрашиваемого сервиса.</param>
86 /// <param name="serviceType">Тип запрашиваемого сервиса.</param>
73 /// <param name="service">Искомый сервис.</param>
87 /// <param name="service">Искомый сервис.</param>
74 public virtual bool TryGetService(Type serviceType, out object service) {
88 public virtual bool TryGetService(Type serviceType, out object service) {
75 if (serviceType == null)
89 Safe.ArgumentNotNull(serviceType, "serviceType");
76 throw new ArgumentNullException("serviceType");
77 AssertNotDisposed();
90 AssertNotDisposed();
78
91
79 ServiceEntry se;
92 ServiceEntry se;
@@ -151,21 +164,26 namespace Implab {
151 /// </summary>
164 /// </summary>
152 /// <typeparam name="T">Тип регистрируемого сервиса.</typeparam>
165 /// <typeparam name="T">Тип регистрируемого сервиса.</typeparam>
153 /// <param name="activator">Фабрика для создания/получения объекта, предоставляющего сервис.</param>
166 /// <param name="activator">Фабрика для создания/получения объекта, предоставляющего сервис.</param>
167 /// <param name = "cleanup">Метод для освобождения экземпляра сервиса, будет вызыван при освобождении сервис-локатора.</param>
154 /// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception>
168 /// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception>
155 /// <remarks>При освобождении сервис-локатора, сервисы полученные в результате активации также будут освобождены.</remarks>
169 /// <remarks>При освобождении сервис-локатора, сервисы полученные в результате активации также будут освобождены.</remarks>
156 public void Register<T>(Func<T> activator) {
170 public void Register<T>(Func<T> activator, Action<T> cleanup) {
157 if (activator == null)
171 Safe.ArgumentNotNull(activator, "activator");
158 throw new ArgumentNullException("activator");
159
172
160 AssertNotDisposed();
173 AssertNotDisposed();
161
174
162 Unregister(typeof(T));
175 Unregister(typeof(T));
163
176
164 m_services[typeof(T)] = new ServiceEntry {
177 m_services[typeof(T)] = new ServiceEntry {
165 activator = () => activator() as object
178 activator = () => activator(),
179 cleanup = instance => cleanup((T)instance)
166 };
180 };
167 }
181 }
168
182
183 public void Register<T>(Func<T> activator) {
184 Register(activator, null);
185 }
186
169 /// <summary>
187 /// <summary>
170 /// Регистрирует объект, предоставляющий сервис.
188 /// Регистрирует объект, предоставляющий сервис.
171 /// </summary>
189 /// </summary>
@@ -185,8 +203,7 namespace Implab {
185 /// <param name="shared">Признак того, что объект является разделяемым и сервис-локатор не должен его освобождать.</param>
203 /// <param name="shared">Признак того, что объект является разделяемым и сервис-локатор не должен его освобождать.</param>
186 /// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception>
204 /// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception>
187 public void Register<T>(T service, bool shared) {
205 public void Register<T>(T service, bool shared) {
188 if (service == null)
206 Safe.ArgumentNotNull(service, "service");
189 throw new ArgumentNullException("service");
190
207
191 AssertNotDisposed();
208 AssertNotDisposed();
192
209
@@ -196,8 +213,7 namespace Implab {
196 }
213 }
197
214
198 public void Unregister(Type serviceType) {
215 public void Unregister(Type serviceType) {
199 if (serviceType == null)
216 Safe.ArgumentNotNull(serviceType, "serviceType");
200 throw new ArgumentNullException("serviceType");
201
217
202 AssertNotDisposed();
218 AssertNotDisposed();
203
219
@@ -223,8 +239,7 namespace Implab {
223 if (disposing) {
239 if (disposing) {
224
240
225 foreach (var entry in m_services.Values)
241 foreach (var entry in m_services.Values)
226 if (!entry.shared && entry.service is IDisposable)
242 entry.Dispose();
227 ((IDisposable)entry.service).Dispose();
228
243
229 }
244 }
230 base.Dispose(disposing);
245 base.Dispose(disposing);
General Comments 0
You need to be logged in to leave comments. Login now