diff --git a/Implab/ServiceLocator.cs b/Implab/ServiceLocator.cs --- a/Implab/ServiceLocator.cs +++ b/Implab/ServiceLocator.cs @@ -1,21 +1,35 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Diagnostics; namespace Implab { /// /// Коллекция сервисов, позволяет регистрировать и получать сервисы. /// public class ServiceLocator: Component, IServiceLocator, IServiceProvider { - // запись об сервисе - struct ServiceEntry { + // запись о сервисе + struct ServiceEntry : IDisposable { public object service; // сервис public bool shared; // признак того, что сервис НЕ нужно освобождать public Func activator; // активатор сервиса при первом обращении + public Action cleanup; // функция для очистки сервиса public List 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 @@ namespace Implab { /// Тип запрашиваемого сервиса. /// Искомый сервис. 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 @@ namespace Implab { /// /// Тип регистрируемого сервиса. /// Фабрика для создания/получения объекта, предоставляющего сервис. + /// Метод для освобождения экземпляра сервиса, будет вызыван при освобождении сервис-локатора. /// Указанный сервис уже зарегистрирован. /// При освобождении сервис-локатора, сервисы полученные в результате активации также будут освобождены. - public void Register(Func activator) { - if (activator == null) - throw new ArgumentNullException("activator"); + public void Register(Func activator, Action 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(Func activator) { + Register(activator, null); + } + /// /// Регистрирует объект, предоставляющий сервис. /// @@ -185,8 +203,7 @@ namespace Implab { /// Признак того, что объект является разделяемым и сервис-локатор не должен его освобождать. /// Указанный сервис уже зарегистрирован. public void Register(T service, bool shared) { - if (service == null) - throw new ArgumentNullException("service"); + Safe.ArgumentNotNull(service, "service"); AssertNotDisposed(); @@ -196,8 +213,7 @@ namespace Implab { } public void Unregister(Type serviceType) { - if (serviceType == null) - throw new ArgumentNullException("serviceType"); + Safe.ArgumentNotNull(serviceType, "serviceType"); AssertNotDisposed(); @@ -223,8 +239,7 @@ namespace Implab { 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);