Mercurial > pub > ImplabNet
comparison Implab/ServiceLocator.cs @ 69:48763f3b5db8
service locator refactoring
| author | cin | 
|---|---|
| date | Thu, 28 Aug 2014 19:38:39 +0400 | 
| parents | 9dd6a896a385 | 
| children | b33832ab0262 | 
   comparison
  equal
  deleted
  inserted
  replaced
| 68:9dd6a896a385 | 69:48763f3b5db8 | 
|---|---|
| 1 using System; | 1 using System; | 
| 2 using System.Collections.Generic; | 2 using System.Collections.Generic; | 
| 3 using System.Linq; | 3 using System.Linq; | 
| 4 using System.Web; | 4 using System.Web; | 
| 5 using System.Diagnostics; | |
| 5 | 6 | 
| 6 namespace Implab { | 7 namespace Implab { | 
| 7 /// <summary> | 8 /// <summary> | 
| 8 /// Коллекция сервисов, позволяет регистрировать и получать сервисы. | 9 /// Коллекция сервисов, позволяет регистрировать и получать сервисы. | 
| 9 /// </summary> | 10 /// </summary> | 
| 16 public List<Type> associated; // ссылки на текущую запись | 17 public List<Type> associated; // ссылки на текущую запись | 
| 17 public Type origin; // ссылка на оригинальную запись о сервисе | 18 public Type origin; // ссылка на оригинальную запись о сервисе | 
| 18 } | 19 } | 
| 19 | 20 | 
| 20 // словарь существующих сервисов | 21 // словарь существующих сервисов | 
| 21 Dictionary<Type, ServiceEntry> m_services = new Dictionary<Type,ServiceEntry>(); | 22 readonly Dictionary<Type, ServiceEntry> m_services = new Dictionary<Type,ServiceEntry>(); | 
| 22 | 23 | 
| 23 /// <summary> | 24 /// <summary> | 
| 24 /// Получает объект предоставляющий сервис <typeparamref name="T"/>. | 25 /// Получает объект предоставляющий сервис <typeparamref name="T"/>. | 
| 25 /// </summary> | 26 /// </summary> | 
| 26 /// <typeparam name="T">Тип запрашиваемого сервиса</typeparam> | 27 /// <typeparam name="T">Тип запрашиваемого сервиса</typeparam> | 
| 27 /// <returns>Объект, реализующий сервис</returns> | 28 /// <returns>Объект, реализующий сервис</returns> | 
| 28 /// <exception cref="KeyNotFoundException">Сервис не зарегистрирован</exception> | 29 /// <exception cref="KeyNotFoundException">Сервис не зарегистрирован</exception> | 
| 29 public T GetService<T>() { | 30 public T GetService<T>() { | 
| 30 return (T)GetService(typeof(T)); | 31 object result; | 
| 32 if (TryGetService(typeof(T), out result)) | |
| 33 return (T)result; | |
| 34 throw new ApplicationException (String.Format ("{0} doesn't provide {1} service", this, typeof(T))); | |
| 31 } | 35 } | 
| 32 | 36 | 
| 33 | 37 | 
| 34 /// <summary> | 38 /// <summary> | 
| 35 /// Пытается получить указанный сервис, в случае, если компонента не предоставляет требуемый сервис | 39 /// Пытается получить указанный сервис, в случае, если компонента не предоставляет требуемый сервис | 
| 37 /// </summary> | 41 /// </summary> | 
| 38 /// <typeparam name="T">Тип требуемого сервиса.</typeparam> | 42 /// <typeparam name="T">Тип требуемого сервиса.</typeparam> | 
| 39 /// <param name="service">Объект реализующий сервис, или <c>default(T)</c> если такового нет.</param> | 43 /// <param name="service">Объект реализующий сервис, или <c>default(T)</c> если такового нет.</param> | 
| 40 /// <returns><c>true</c> - сервис найден, <c>false</c> - сервис не зарегистрирован.</returns> | 44 /// <returns><c>true</c> - сервис найден, <c>false</c> - сервис не зарегистрирован.</returns> | 
| 41 public bool TryGetService<T>(out T service) { | 45 public bool TryGetService<T>(out T service) { | 
| 42 AssertNotDisposed(); | 46 object result; | 
| 43 | 47 if (TryGetService(typeof(T), out result)) { | 
| 44 var result = GetService(typeof(T), false); | 48 service = (T)result; | 
| 45 if (result == null) { | 49 return true; | 
| 46 service = default(T); | 50 } | 
| 47 return false; | 51 service = default(T); | 
| 48 } else { | 52 return false; | 
| 49 service = (T)result; | |
| 50 return true; | |
| 51 } | |
| 52 } | 53 } | 
| 53 | 54 | 
| 54 /// <summary> | 55 /// <summary> | 
| 55 /// Получает объект предоставляющий сервис <paramref name="serviceType"/> | 56 /// Получает объект предоставляющий сервис <paramref name="serviceType"/> | 
| 56 /// </summary> | 57 /// </summary> | 
| 57 /// <param name="serviceType">Тип запрашиваемого сервиса</param> | 58 /// <param name="serviceType">Тип запрашиваемого сервиса</param> | 
| 58 /// <returns>Объект, реализующий сервис</returns> | 59 /// <returns>Объект, реализующий сервис</returns> | 
| 59 /// <exception cref="KeyNotFoundException">Сервис не зарегистрирован</exception> | 60 /// <exception cref="KeyNotFoundException">Сервис не зарегистрирован</exception> | 
| 60 public object GetService(Type serviceType) { | 61 public object GetService(Type serviceType) { | 
| 61 return GetService (serviceType, true); | 62 object result; | 
| 63 if (TryGetService(serviceType, out result)) | |
| 64 return result; | |
| 65 throw new ApplicationException (String.Format ("{0} doesn't provide {1} service", this, serviceType)); | |
| 62 } | 66 } | 
| 63 | 67 | 
| 64 public virtual object GetService(Type serviceType, bool throwOnError) { | 68 /// <summary> | 
| 69 /// Пытается получить требуемый сервис или совместимый с ним. | |
| 70 /// </summary> | |
| 71 /// <returns><c>true</c>, если сервис был найден, <c>false</c> в противном случае..</returns> | |
| 72 /// <param name="serviceType">Тип запрашиваемого сервиса.</param> | |
| 73 /// <param name="service">Искомый сервис.</param> | |
| 74 public virtual bool TryGetService(Type serviceType, out object service) { | |
| 65 if (serviceType == null) | 75 if (serviceType == null) | 
| 66 throw new ArgumentNullException("serviceType"); | 76 throw new ArgumentNullException("serviceType"); | 
| 67 AssertNotDisposed(); | 77 AssertNotDisposed(); | 
| 68 | 78 | 
| 69 ServiceEntry se; | 79 ServiceEntry se; | 
| 71 // ищем ближайщий объект, реализующий нужный сервис | 81 // ищем ближайщий объект, реализующий нужный сервис | 
| 72 Type pt = null; | 82 Type pt = null; | 
| 73 foreach (var t in m_services.Keys) | 83 foreach (var t in m_services.Keys) | 
| 74 if (serviceType.IsAssignableFrom(t) && (pt == null || t.IsAssignableFrom(pt))) | 84 if (serviceType.IsAssignableFrom(t) && (pt == null || t.IsAssignableFrom(pt))) | 
| 75 pt = t; | 85 pt = t; | 
| 76 if (pt == null) | 86 | 
| 77 throw new ApplicationException(String.Format("{0} doesn't provide {1} service",this,serviceType)); | 87 if (pt == null) { | 
| 88 // нет нужного сервиса | |
| 89 service = null; | |
| 90 return false; | |
| 91 } | |
| 78 | 92 | 
| 79 var pe = m_services[pt]; | 93 var pe = m_services[pt]; | 
| 80 | 94 | 
| 81 // найденная запись может ссылаться на оригинальную запись с сервисом | 95 // найденная запись может ссылаться на оригинальную запись с сервисом | 
| 82 if(pe.origin != null) { | 96 if(pe.origin != null) { | 
| 102 | 116 | 
| 103 m_services[serviceType] = se; | 117 m_services[serviceType] = se; | 
| 104 } | 118 } | 
| 105 | 119 | 
| 106 // запись содержит в себе информацию о сервисе | 120 // запись содержит в себе информацию о сервисе | 
| 107 if (se.service != null) | 121 if (se.service != null) { | 
| 108 return se.service; | 122 service = se.service; | 
| 123 return true; | |
| 124 } | |
| 109 | 125 | 
| 110 // текущая запись является ссылкой | 126 // текущая запись является ссылкой | 
| 111 if (se.origin != null) { | 127 if (se.origin != null) { | 
| 112 se.service = GetService(se.origin); | 128 se.service = GetService(se.origin); | 
| 113 m_services[serviceType] = se; | 129 m_services[serviceType] = se; | 
| 114 return se.service; | 130 service = se.service; | 
| 131 return true; | |
| 115 } | 132 } | 
| 116 | 133 | 
| 117 // текущая запись не является ссылкой и не имеет информации о сервисе | 134 // текущая запись не является ссылкой и не имеет информации о сервисе | 
| 118 // она должна сожержать информацию об активации | 135 // она должна сожержать информацию об активации | 
| 119 if (se.activator != null) { | 136 if (se.activator != null) { | 
| 120 se.service = se.activator(); | 137 se.service = se.activator(); | 
| 121 | 138 | 
| 122 m_services[serviceType] = se; | 139 m_services[serviceType] = se; | 
| 123 | 140 | 
| 124 return se.service; | 141 service = se.service; | 
| 125 } | 142 return true; | 
| 126 | 143 } | 
| 127 if (throwOnError) | 144 | 
| 128 throw new Exception("Unable to create a service instance"); | 145 service = null; | 
| 129 return null; | 146 return false; | 
| 130 } | 147 } | 
| 131 | 148 | 
| 132 /// <summary> | 149 /// <summary> | 
| 133 /// Регистрирует фабрику для активации сервиса по первому требованию. | 150 /// Регистрирует фабрику для активации сервиса по первому требованию. | 
| 134 /// </summary> | 151 /// </summary> | 
