Mercurial > pub > ImplabNet
changeset 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 | abe260860bd6 |
children | 79badb3ed195 |
files | Implab/ServiceLocator.cs |
diffstat | 1 files changed, 32 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/Implab/ServiceLocator.cs Tue Sep 30 16:05:35 2014 +0400 +++ b/Implab/ServiceLocator.cs Mon Oct 06 03:41:17 2014 +0400 @@ -1,21 +1,35 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Diagnostics; namespace Implab { /// <summary> /// Коллекция сервисов, позволяет регистрировать и получать сервисы. /// </summary> public class ServiceLocator: Component, IServiceLocator, IServiceProvider { - // запись об сервисе - struct ServiceEntry { + // запись о сервисе + struct ServiceEntry : IDisposable { public object service; // сервис public bool shared; // признак того, что сервис НЕ нужно освобождать public Func<object> activator; // активатор сервиса при первом обращении + public Action<object> cleanup; // функция для очистки сервиса public List<Type> associated; // ссылки на текущую запись public Type origin; // ссылка на оригинальную запись о сервисе + + #region IDisposable implementation + + public void Dispose() { + if (shared) + return; + if (cleanup != null) + cleanup(service); + else { + var d = service as IDisposable; + if (d != null) + d.Dispose(); + } + } + + #endregion } // словарь существующих сервисов @@ -72,8 +86,7 @@ /// <param name="serviceType">Тип запрашиваемого сервиса.</param> /// <param name="service">Искомый сервис.</param> public virtual bool TryGetService(Type serviceType, out object service) { - if (serviceType == null) - throw new ArgumentNullException("serviceType"); + Safe.ArgumentNotNull(serviceType, "serviceType"); AssertNotDisposed(); ServiceEntry se; @@ -151,21 +164,26 @@ /// </summary> /// <typeparam name="T">Тип регистрируемого сервиса.</typeparam> /// <param name="activator">Фабрика для создания/получения объекта, предоставляющего сервис.</param> + /// <param name = "cleanup">Метод для освобождения экземпляра сервиса, будет вызыван при освобождении сервис-локатора.</param> /// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception> /// <remarks>При освобождении сервис-локатора, сервисы полученные в результате активации также будут освобождены.</remarks> - public void Register<T>(Func<T> activator) { - if (activator == null) - throw new ArgumentNullException("activator"); + public void Register<T>(Func<T> activator, Action<T> cleanup) { + Safe.ArgumentNotNull(activator, "activator"); AssertNotDisposed(); Unregister(typeof(T)); m_services[typeof(T)] = new ServiceEntry { - activator = () => activator() as object + activator = () => activator(), + cleanup = instance => cleanup((T)instance) }; } + public void Register<T>(Func<T> activator) { + Register(activator, null); + } + /// <summary> /// Регистрирует объект, предоставляющий сервис. /// </summary> @@ -185,8 +203,7 @@ /// <param name="shared">Признак того, что объект является разделяемым и сервис-локатор не должен его освобождать.</param> /// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception> public void Register<T>(T service, bool shared) { - if (service == null) - throw new ArgumentNullException("service"); + Safe.ArgumentNotNull(service, "service"); AssertNotDisposed(); @@ -196,8 +213,7 @@ } public void Unregister(Type serviceType) { - if (serviceType == null) - throw new ArgumentNullException("serviceType"); + Safe.ArgumentNotNull(serviceType, "serviceType"); AssertNotDisposed(); @@ -223,8 +239,7 @@ if (disposing) { foreach (var entry in m_services.Values) - if (!entry.shared && entry.service is IDisposable) - ((IDisposable)entry.service).Dispose(); + entry.Dispose(); } base.Dispose(disposing);