Mercurial > pub > ImplabNet
comparison Implab/ServiceLocator.cs @ 86:b33832ab0262 v2
ServiceLocator: added a cleanup callback to the service registration method
author | cin |
---|---|
date | Mon, 06 Oct 2014 03:41:17 +0400 |
parents | 48763f3b5db8 |
children | 79badb3ed195 |
comparison
equal
deleted
inserted
replaced
85:abe260860bd6 | 86:b33832ab0262 |
---|---|
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 // словарь существующих сервисов |
22 readonly Dictionary<Type, ServiceEntry> m_services = new Dictionary<Type,ServiceEntry>(); | 36 readonly Dictionary<Type, ServiceEntry> m_services = new Dictionary<Type,ServiceEntry>(); |
23 | 37 |
70 /// </summary> | 84 /// </summary> |
71 /// <returns><c>true</c>, если сервис был найден, <c>false</c> в противном случае..</returns> | 85 /// <returns><c>true</c>, если сервис был найден, <c>false</c> в противном случае..</returns> |
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; |
80 if (!m_services.TryGetValue(serviceType, out se)) { | 93 if (!m_services.TryGetValue(serviceType, out se)) { |
81 // ищем ближайщий объект, реализующий нужный сервис | 94 // ищем ближайщий объект, реализующий нужный сервис |
149 /// <summary> | 162 /// <summary> |
150 /// Регистрирует фабрику для активации сервиса по первому требованию. | 163 /// Регистрирует фабрику для активации сервиса по первому требованию. |
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 }; |
181 } | |
182 | |
183 public void Register<T>(Func<T> activator) { | |
184 Register(activator, null); | |
167 } | 185 } |
168 | 186 |
169 /// <summary> | 187 /// <summary> |
170 /// Регистрирует объект, предоставляющий сервис. | 188 /// Регистрирует объект, предоставляющий сервис. |
171 /// </summary> | 189 /// </summary> |
183 /// <typeparam name="T">Тип регистрируемого сервиса.</typeparam> | 201 /// <typeparam name="T">Тип регистрируемого сервиса.</typeparam> |
184 /// <param name="service">Объект, предоставляющий сервис.</param> | 202 /// <param name="service">Объект, предоставляющий сервис.</param> |
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 |
193 Unregister(typeof(T)); | 210 Unregister(typeof(T)); |
194 | 211 |
195 m_services[typeof(T)] = new ServiceEntry { service = service, shared = shared }; | 212 m_services[typeof(T)] = new ServiceEntry { service = service, shared = shared }; |
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 |
204 ServiceEntry se; | 220 ServiceEntry se; |
205 if (m_services.TryGetValue(serviceType, out se)) { | 221 if (m_services.TryGetValue(serviceType, out se)) { |
221 /// <param name="disposing">Призанак того, что нужно освободить ресурсы.</param> | 237 /// <param name="disposing">Призанак того, что нужно освободить ресурсы.</param> |
222 protected override void Dispose(bool disposing) { | 238 protected override void Dispose(bool disposing) { |
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); |
231 } | 246 } |
232 } | 247 } |