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