##// END OF EJS Templates
improved tracing...
improved tracing added the application components container MTComponentContainer.AppContainer

File last commit:

r88:c4877ae77cee v2
r93:dc4942d09e74 v2
Show More
ServiceLocator.cs
247 lines | 11.6 KiB | text/x-csharp | CSharpLexer
cin
improved tracing...
r40 using System;
using System.Collections.Generic;
namespace Implab {
/// <summary>
/// Коллекция сервисов, позволяет регистрировать и получать сервисы.
/// </summary>
public class ServiceLocator: Component, IServiceLocator, IServiceProvider {
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 // запись о сервисе
struct ServiceEntry : IDisposable {
cin
improved tracing...
r40 public object service; // сервис
public bool shared; // признак того, что сервис НЕ нужно освобождать
public Func<object> activator; // активатор сервиса при первом обращении
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 public Action<object> cleanup; // функция для очистки сервиса
cin
improved tracing...
r40 public List<Type> associated; // ссылки на текущую запись
public Type origin; // ссылка на оригинальную запись о сервисе
cin
ServiceLocator: added a cleanup callback to the service registration method
r86
#region IDisposable implementation
public void Dispose() {
if (shared)
return;
cin
ServiceLocator: fixed services cleanup
r88 if (cleanup != null) {
if (service != null)
cleanup(service);
} else
Safe.Dispose(service);
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 }
#endregion
cin
improved tracing...
r40 }
// словарь существующих сервисов
cin
service locator refactoring
r69 readonly Dictionary<Type, ServiceEntry> m_services = new Dictionary<Type,ServiceEntry>();
cin
improved tracing...
r40
/// <summary>
/// Получает объект предоставляющий сервис <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">Тип запрашиваемого сервиса</typeparam>
/// <returns>Объект, реализующий сервис</returns>
/// <exception cref="KeyNotFoundException">Сервис не зарегистрирован</exception>
public T GetService<T>() {
cin
service locator refactoring
r69 object result;
if (TryGetService(typeof(T), out result))
return (T)result;
throw new ApplicationException (String.Format ("{0} doesn't provide {1} service", this, typeof(T)));
cin
improved tracing...
r40 }
/// <summary>
/// Пытается получить указанный сервис, в случае, если компонента не предоставляет требуемый сервис
/// не возникает исключений.
/// </summary>
/// <typeparam name="T">Тип требуемого сервиса.</typeparam>
/// <param name="service">Объект реализующий сервис, или <c>default(T)</c> если такового нет.</param>
/// <returns><c>true</c> - сервис найден, <c>false</c> - сервис не зарегистрирован.</returns>
public bool TryGetService<T>(out T service) {
cin
service locator refactoring
r69 object result;
if (TryGetService(typeof(T), out result)) {
service = (T)result;
return true;
}
service = default(T);
return false;
cin
improved tracing...
r40 }
/// <summary>
/// Получает объект предоставляющий сервис <paramref name="serviceType"/>
/// </summary>
/// <param name="serviceType">Тип запрашиваемого сервиса</param>
/// <returns>Объект, реализующий сервис</returns>
/// <exception cref="KeyNotFoundException">Сервис не зарегистрирован</exception>
cin
ServiceLocator: small refactoring, GetService method is made virtual
r68 public object GetService(Type serviceType) {
cin
service locator refactoring
r69 object result;
if (TryGetService(serviceType, out result))
return result;
throw new ApplicationException (String.Format ("{0} doesn't provide {1} service", this, serviceType));
cin
ServiceLocator: small refactoring, GetService method is made virtual
r68 }
cin
service locator refactoring
r69 /// <summary>
/// Пытается получить требуемый сервис или совместимый с ним.
/// </summary>
/// <returns><c>true</c>, если сервис был найден, <c>false</c> в противном случае..</returns>
/// <param name="serviceType">Тип запрашиваемого сервиса.</param>
/// <param name="service">Искомый сервис.</param>
public virtual bool TryGetService(Type serviceType, out object service) {
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 Safe.ArgumentNotNull(serviceType, "serviceType");
cin
improved tracing...
r40 AssertNotDisposed();
ServiceEntry se;
if (!m_services.TryGetValue(serviceType, out se)) {
// ищем ближайщий объект, реализующий нужный сервис
Type pt = null;
foreach (var t in m_services.Keys)
if (serviceType.IsAssignableFrom(t) && (pt == null || t.IsAssignableFrom(pt)))
pt = t;
cin
service locator refactoring
r69
if (pt == null) {
// нет нужного сервиса
service = null;
return false;
}
cin
improved tracing...
r40
var pe = m_services[pt];
// найденная запись может ссылаться на оригинальную запись с сервисом
if(pe.origin != null) {
pt = pe.origin;
pe = m_services[pt];
}
// добавляем список с обратными ссылками
if (pe.associated == null)
pe.associated = new List<Type>();
pe.associated.Add(serviceType);
// обновляем родительскую запись
m_services[pt] = pe;
// создаем запись со ссылкой
se = new ServiceEntry {
service = pe.service,
origin = pt,
shared = true // предотвращаем множественные попытки освобождения
};
m_services[serviceType] = se;
}
// запись содержит в себе информацию о сервисе
cin
service locator refactoring
r69 if (se.service != null) {
service = se.service;
return true;
}
cin
improved tracing...
r40
// текущая запись является ссылкой
if (se.origin != null) {
se.service = GetService(se.origin);
m_services[serviceType] = se;
cin
service locator refactoring
r69 service = se.service;
return true;
cin
improved tracing...
r40 }
// текущая запись не является ссылкой и не имеет информации о сервисе
// она должна сожержать информацию об активации
if (se.activator != null) {
se.service = se.activator();
m_services[serviceType] = se;
cin
service locator refactoring
r69 service = se.service;
return true;
cin
improved tracing...
r40 }
cin
service locator refactoring
r69 service = null;
return false;
cin
improved tracing...
r40 }
/// <summary>
/// Регистрирует фабрику для активации сервиса по первому требованию.
/// </summary>
/// <typeparam name="T">Тип регистрируемого сервиса.</typeparam>
/// <param name="activator">Фабрика для создания/получения объекта, предоставляющего сервис.</param>
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 /// <param name = "cleanup">Метод для освобождения экземпляра сервиса, будет вызыван при освобождении сервис-локатора.</param>
cin
improved tracing...
r40 /// <remarks>При освобождении сервис-локатора, сервисы полученные в результате активации также будут освобождены.</remarks>
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 public void Register<T>(Func<T> activator, Action<T> cleanup) {
Safe.ArgumentNotNull(activator, "activator");
cin
improved tracing...
r40
AssertNotDisposed();
Unregister(typeof(T));
cin
ServiceLocator: fixed services cleanup
r88 var serviceEntry = new ServiceEntry();
serviceEntry.activator = () => activator();
if (cleanup != null)
serviceEntry.cleanup = instance => cleanup((T)instance);
m_services[typeof(T)] = serviceEntry;
cin
improved tracing...
r40 }
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 public void Register<T>(Func<T> activator) {
Register(activator, null);
}
cin
improved tracing...
r40 /// <summary>
/// Регистрирует объект, предоставляющий сервис.
/// </summary>
/// <typeparam name="T">Тип регистрируемого сервиса.</typeparam>
/// <param name="service">Объект, предоставляющий сервис.</param>
/// <exception cref="InvalidOperationException">Указанный сервис уже зарегистрирован.</exception>
/// <remarks>Сервис-локатором не управляет временем жизни объекта для зарегистрированного сервиса.</remarks>
public void Register<T>(T service) {
Register(service, true);
}
/// <summary>
cin
minor fixes in the service locator class
r87 /// Регистрирует объект, предоставляющий сервис. Повторная регистрация отменяет уже существующую.
cin
improved tracing...
r40 /// </summary>
/// <typeparam name="T">Тип регистрируемого сервиса.</typeparam>
/// <param name="service">Объект, предоставляющий сервис.</param>
/// <param name="shared">Признак того, что объект является разделяемым и сервис-локатор не должен его освобождать.</param>
public void Register<T>(T service, bool shared) {
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 Safe.ArgumentNotNull(service, "service");
cin
improved tracing...
r40
AssertNotDisposed();
Unregister(typeof(T));
m_services[typeof(T)] = new ServiceEntry { service = service, shared = shared };
}
public void Unregister(Type serviceType) {
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 Safe.ArgumentNotNull(serviceType, "serviceType");
cin
improved tracing...
r40
AssertNotDisposed();
ServiceEntry se;
if (m_services.TryGetValue(serviceType, out se)) {
cin
minor fixes in the service locator class
r87 if (se.origin != null) {
var pe = m_services[se.origin];
pe.associated.Remove(serviceType);
}
cin
improved tracing...
r40 // освобождаем ресурсы
cin
minor fixes in the service locator class
r87 se.Dispose();
cin
improved tracing...
r40 m_services.Remove(serviceType);
// убираем связанные записи
if (se.associated != null)
foreach (var item in se.associated)
m_services.Remove(item);
}
}
/// <summary>
/// Освобождает зарегистрированные сервисы (которые требуется освобоить).
/// </summary>
/// <param name="disposing">Призанак того, что нужно освободить ресурсы.</param>
protected override void Dispose(bool disposing) {
if (disposing) {
foreach (var entry in m_services.Values)
cin
ServiceLocator: added a cleanup callback to the service registration method
r86 entry.Dispose();
cin
improved tracing...
r40
}
base.Dispose(disposing);
}
}
}