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>