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);