| @@ -1,21 +1,35 | |||
| 
             | 
        1 | 1 | using System; | 
| 
             | 
        2 | 2 | using System.Collections.Generic; | 
| 
             | 
        3 | using System.Linq; | |
| 
             | 
        4 | using System.Web; | |
| 
             | 
        5 | using System.Diagnostics; | |
| 
             | 
        6 | 3 | |
| 
             | 
        7 | 4 | namespace Implab { | 
| 
             | 
        8 | 5 | /// <summary> | 
| 
             | 
        9 | 6 | /// Коллекция сервисов, позволяет регистрировать и получать сервисы. | 
| 
             | 
        10 | 7 | /// </summary> | 
| 
             | 
        11 | 8 | public class ServiceLocator: Component, IServiceLocator, IServiceProvider { | 
| 
             | 
        12 | 
            
                     // запись о | 
    |
| 
             | 
        13 | struct ServiceEntry { | |
| 
             | 
        9 | // запись о сервисе | |
| 
             | 
        10 | struct ServiceEntry : IDisposable { | |
| 
             | 
        14 | 11 | public object service; // сервис | 
| 
             | 
        15 | 12 | public bool shared; // признак того, что сервис НЕ нужно освобождать | 
| 
             | 
        16 | 13 | public Func<object> activator; // активатор сервиса при первом обращении | 
| 
             | 
        14 | public Action<object> cleanup; // функция для очистки сервиса | |
| 
             | 
        17 | 15 | public List<Type> associated; // ссылки на текущую запись | 
| 
             | 
        18 | 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 | // словарь существующих сервисов | 
| @@ -72,8 +86,7 namespace Implab { | |||
| 
             | 
        72 | 86 | /// <param name="serviceType">Тип запрашиваемого сервиса.</param> | 
| 
             | 
        73 | 87 | /// <param name="service">Искомый сервис.</param> | 
| 
             | 
        74 | 88 | public virtual bool TryGetService(Type serviceType, out object service) { | 
| 
             | 
        75 | if (serviceType == null) | |
| 
             | 
        76 | throw new ArgumentNullException("serviceType"); | |
| 
             | 
        89 | Safe.ArgumentNotNull(serviceType, "serviceType"); | |
| 
             | 
        77 | 90 | AssertNotDisposed(); | 
| 
             | 
        78 | 91 | |
| 
             | 
        79 | 92 | ServiceEntry se; | 
| @@ -151,21 +164,26 namespace Implab { | |||
| 
             | 
        151 | 164 | /// </summary> | 
| 
             | 
        152 | 165 | /// <typeparam name="T">Тип регистрируемого сервиса.</typeparam> | 
| 
             | 
        153 | 166 | /// <param name="activator">Фабрика для создания/получения объекта, предоставляющего сервис.</param> | 
| 
             | 
        167 | /// <param name = "cleanup">Метод для освобождения экземпляра сервиса, будет вызыван при освобождении сервис-локатора.</param> | |
| 
             | 
        154 | 168 | /// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception> | 
| 
             | 
        155 | 169 | /// <remarks>При освобождении сервис-локатора, сервисы полученные в результате активации также будут освобождены.</remarks> | 
| 
             | 
        156 | public void Register<T>(Func<T> activator) { | |
| 
             | 
        157 | if (activator == null) | |
| 
             | 
        158 | throw new ArgumentNullException("activator"); | |
| 
             | 
        170 | public void Register<T>(Func<T> activator, Action<T> cleanup) { | |
| 
             | 
        171 | Safe.ArgumentNotNull(activator, "activator"); | |
| 
             | 
        159 | 172 | |
| 
             | 
        160 | 173 | AssertNotDisposed(); | 
| 
             | 
        161 | 174 | |
| 
             | 
        162 | 175 | Unregister(typeof(T)); | 
| 
             | 
        163 | 176 | |
| 
             | 
        164 | 177 | m_services[typeof(T)] = new ServiceEntry { | 
| 
             | 
        165 | 
            
                             activator = () => activator() | 
    |
| 
             | 
        178 | activator = () => activator(), | |
| 
             | 
        179 | cleanup = instance => cleanup((T)instance) | |
| 
             | 
        166 | 180 | }; | 
| 
             | 
        167 | 181 | } | 
| 
             | 
        168 | 182 | |
| 
             | 
        183 | public void Register<T>(Func<T> activator) { | |
| 
             | 
        184 | Register(activator, null); | |
| 
             | 
        185 | } | |
| 
             | 
        186 | ||
| 
             | 
        169 | 187 | /// <summary> | 
| 
             | 
        170 | 188 | /// Регистрирует объект, предоставляющий сервис. | 
| 
             | 
        171 | 189 | /// </summary> | 
| @@ -185,8 +203,7 namespace Implab { | |||
| 
             | 
        185 | 203 | /// <param name="shared">Признак того, что объект является разделяемым и сервис-локатор не должен его освобождать.</param> | 
| 
             | 
        186 | 204 | /// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception> | 
| 
             | 
        187 | 205 | public void Register<T>(T service, bool shared) { | 
| 
             | 
        188 | if (service == null) | |
| 
             | 
        189 | throw new ArgumentNullException("service"); | |
| 
             | 
        206 | Safe.ArgumentNotNull(service, "service"); | |
| 
             | 
        190 | 207 | |
| 
             | 
        191 | 208 | AssertNotDisposed(); | 
| 
             | 
        192 | 209 | |
| @@ -196,8 +213,7 namespace Implab { | |||
| 
             | 
        196 | 213 | } | 
| 
             | 
        197 | 214 | |
| 
             | 
        198 | 215 | public void Unregister(Type serviceType) { | 
| 
             | 
        199 | if (serviceType == null) | |
| 
             | 
        200 | throw new ArgumentNullException("serviceType"); | |
| 
             | 
        216 | Safe.ArgumentNotNull(serviceType, "serviceType"); | |
| 
             | 
        201 | 217 | |
| 
             | 
        202 | 218 | AssertNotDisposed(); | 
| 
             | 
        203 | 219 | |
| @@ -223,8 +239,7 namespace Implab { | |||
| 
             | 
        223 | 239 | if (disposing) { | 
| 
             | 
        224 | 240 | |
| 
             | 
        225 | 241 | foreach (var entry in m_services.Values) | 
| 
             | 
        226 | 
            
                                  | 
    |
| 
             | 
        227 | ((IDisposable)entry.service).Dispose(); | |
| 
             | 
        242 | entry.Dispose(); | |
| 
             | 
        228 | 243 | |
| 
             | 
        229 | 244 | } | 
| 
             | 
        230 | 245 | base.Dispose(disposing); | 
        
        General Comments 0
    
    
  
  
                      You need to be logged in to leave comments.
                      Login now
                    
                