/src/Engine/MvcTurbine.Unity/UnityServiceLocator.cs

https://github.com/tyronegroves/mvcturbine · C# · 292 lines · 141 code · 40 blank · 111 comment · 10 complexity · 93a2aa010856403a1224f9874551d18b MD5 · raw file

  1. namespace MvcTurbine.Unity {
  2. using System;
  3. using System.Collections.Generic;
  4. using ComponentModel;
  5. using Microsoft.Practices.Unity;
  6. /// <summary>
  7. /// Default implementation of the <seealso cref="IServiceLocator"/> contract with Unity IoC.
  8. /// </summary>
  9. /// <remarks>
  10. /// To learn more about Unity, please visit its website: http://www.codeplex.com/unity
  11. /// </remarks>
  12. [Serializable]
  13. public class UnityServiceLocator : IServiceLocator, IServiceReleaser, IServiceInjector {
  14. private static bool isDisposing;
  15. /// <summary>
  16. /// Creates an instance of the locator with an empty <seealso cref="IUnityContainer"/> instance.
  17. /// </summary>
  18. public UnityServiceLocator()
  19. : this(new UnityContainer()) {
  20. }
  21. /// <summary>
  22. /// Creates an instance of the locator with the specified <seealso cref="IUnityContainer"/> instance.
  23. /// </summary>
  24. /// <param name="container">Instance of <seealso cref="IUnityContainer"/> to use.</param>
  25. public UnityServiceLocator(IUnityContainer container) {
  26. if (container == null) {
  27. throw new ArgumentNullException("container", "The specified Unity container cannot be null.");
  28. }
  29. Container = container;
  30. }
  31. /// <summary>
  32. /// Gets the current <seealso cref="IUnityContainer"/> associated with this instance.
  33. /// </summary>
  34. public IUnityContainer Container { private set; get; }
  35. public IList<object> ResolveServices(Type type) {
  36. return new List<object>(Container.ResolveAll(type));
  37. }
  38. /// <summary>
  39. /// Gets the associated <see cref="IServiceRegistrar"/> to process.
  40. /// </summary>
  41. /// <returns></returns>
  42. public IServiceRegistrar Batch() {
  43. return new RegistrationStub();
  44. }
  45. /// <summary>
  46. /// Resolves the service of the specified type.
  47. /// </summary>
  48. /// <typeparam name="T">Type of service to resolve.</typeparam>
  49. /// <returns>An instance of the type, null otherwise.</returns>
  50. public T Resolve<T>() where T : class {
  51. try {
  52. return Container.Resolve<T>();
  53. }
  54. catch (Exception ex) {
  55. throw new ServiceResolutionException(typeof(T), ex);
  56. }
  57. }
  58. /// <summary>
  59. /// Resolves the service of the specified type by the given string key.
  60. /// </summary>
  61. /// <typeparam name="T">Type of service to resolve.</typeparam>
  62. /// <param name="key">Unique key to distinguish the service.</param>
  63. /// <returns>An instance of the type, null otherwise.</returns>
  64. public T Resolve<T>(string key) where T : class {
  65. try {
  66. return Container.Resolve<T>(key);
  67. }
  68. catch (Exception ex) {
  69. throw new ServiceResolutionException(typeof(T), ex);
  70. }
  71. }
  72. /// <summary>
  73. /// Resolves the service of the specified type by the given type key.
  74. /// </summary>
  75. /// <typeparam name="T">Type of service to resolve.</typeparam>
  76. /// <param name="type">Key type of the service.</param>
  77. /// <returns>An instance of the type, null otherwise.</returns>
  78. public T Resolve<T>(Type type) where T : class {
  79. try {
  80. return Container.Resolve(type) as T;
  81. }
  82. catch (Exception ex) {
  83. throw new ServiceResolutionException(type, ex);
  84. }
  85. }
  86. ///<summary>
  87. /// Resolves the service of the specified type by the given type key.
  88. ///</summary>
  89. ///<param name="type">Type of service to resolve.</param>
  90. ///<returns>An instance of the type, null otherwise</returns>
  91. public object Resolve(Type type) {
  92. try {
  93. return Container.Resolve(type);
  94. }
  95. catch (Exception ex) {
  96. throw new ServiceResolutionException(type, ex);
  97. }
  98. }
  99. /// <summary>
  100. /// Resolves the list of services of type <see cref="T"/> that are registered
  101. /// within the locator.
  102. /// </summary>
  103. /// <typeparam name="T">Type of the service to resolve.</typeparam>
  104. /// <returns>A list of service of type <see cref="T"/>, null otherwise.</returns>
  105. public IList<T> ResolveServices<T>() where T : class {
  106. IEnumerable<T> services = Container.ResolveAll<T>();
  107. return new List<T>(services);
  108. }
  109. /// <summary>
  110. /// Registers the implemation type, <paramref name="implType"/>, with the locator under
  111. /// the <see cref="Interface"/> service type.
  112. /// </summary>
  113. /// <typeparam name="Interface">Type of the service to register.</typeparam>
  114. /// <param name="implType">Implementation type to use for registration.</param>
  115. public void Register<Interface>(Type implType) where Interface : class {
  116. var key = string.Format("{0}-{1}", typeof(Interface).Name, implType.FullName);
  117. Container.RegisterType(typeof(Interface), implType, key);
  118. // Work-around, also register this implementation to service mapping
  119. // without the generated key above.
  120. Container.RegisterType(typeof(Interface), implType);
  121. }
  122. /// <summary>
  123. /// Registers the implemation type, <see cref="Implementation"/>, with the locator under
  124. /// the <see cref="Interface"/> service type.
  125. /// </summary>
  126. /// <typeparam name="Interface">Type of the service to register.</typeparam>
  127. /// <typeparam name="Implementation">Implementation type to use for registration.
  128. /// </typeparam>
  129. public void Register<Interface, Implementation>()
  130. where Implementation : class, Interface {
  131. Container.RegisterType<Interface, Implementation>();
  132. }
  133. /// <summary>
  134. /// Registers the implemation type, <see cref="Implementation"/>, with the locator under
  135. /// the <see cref="Interface"/> service type.
  136. /// </summary>
  137. /// <typeparam name="Interface">Type of the service to register.</typeparam>
  138. /// <typeparam name="Implementation">Implementation type to use for registration.
  139. /// </typeparam>
  140. /// <param name="key">Unique key to distinguish the service.</param>
  141. public void Register<Interface, Implementation>(string key)
  142. where Implementation : class, Interface {
  143. Container.RegisterType<Interface, Implementation>(key);
  144. }
  145. /// <summary>
  146. /// Registers the implementation type, <paramref name="type"/>, with the locator
  147. /// by the given string key.
  148. /// </summary>
  149. /// <param name="key">Unique key to distinguish the service.</param>
  150. /// <param name="type">Implementation type to use.</param>
  151. public void Register(string key, Type type) {
  152. Container.RegisterType(type, key);
  153. }
  154. /// <summary>
  155. /// Registers the implementation type, <paramref name="implType"/>, with the locator
  156. /// by the given service type, <paramref name="serviceType"/>
  157. /// </summary>
  158. /// <param name="serviceType">Type of the service to register.</param>
  159. /// <param name="implType">Implementation to associate with the service.</param>
  160. public void Register(Type serviceType, Type implType) {
  161. Container.RegisterType(serviceType, implType);
  162. }
  163. /// <summary>
  164. /// Registers the implementation type, <paramref name="implType"/>, with the locator
  165. /// by the given service type, <paramref name="serviceType"/>
  166. /// </summary>
  167. /// <param name="serviceType">Type of the service to register.</param>
  168. /// <param name="implType">Implementation to associate with the service.</param>
  169. /// <param name="key"></param>
  170. public void Register(Type serviceType, Type implType, string key) {
  171. Container.RegisterType(serviceType, implType, key);
  172. }
  173. /// <summary>
  174. /// Registers the instance of type, <typeparamref name="Interface"/>, with the locator.
  175. /// </summary>
  176. /// <typeparam name="Interface">Type of the service to register.</typeparam>
  177. /// <param name="instance">Instance of the type to register.</param>
  178. public void Register<Interface>(Interface instance) where Interface : class {
  179. Container.RegisterInstance(instance);
  180. }
  181. /// <summary>
  182. /// Resolves the service of the specified interface with the provided factory method.
  183. /// </summary>
  184. /// <param name="factoryMethod">The factory method which will be used to resolve this interface.</param>
  185. /// <returns>An instance of the type, null otherwise</returns>
  186. public void Register<Interface>(Func<Interface> factoryMethod) where Interface : class {
  187. var container = this.Container;
  188. Func<IUnityContainer, object> factoryFunc = c => factoryMethod.Invoke();
  189. container.RegisterType<Interface>(new InjectionFactory(factoryFunc));
  190. }
  191. /// <summary>
  192. /// Releases (disposes) the service instance from within the locator.
  193. /// </summary>
  194. /// <param name="instance">Instance of a service to dipose from the locator.</param>
  195. public void Release(object instance) {
  196. if (instance == null) return;
  197. Container.Teardown(instance);
  198. }
  199. public TService Inject<TService>(TService instance) where TService : class {
  200. return instance == null ? instance : (TService)Container.BuildUp(instance.GetType(), instance);
  201. }
  202. public void TearDown<TService>(TService instance) where TService : class {
  203. if (instance == null) return;
  204. Container.Teardown(instance);
  205. }
  206. /// <summary>
  207. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  208. /// </summary>
  209. /// <filterpriority>2</filterpriority>
  210. public void Dispose() {
  211. if (isDisposing) return;
  212. if (Container == null) return;
  213. isDisposing = true;
  214. Container.Dispose();
  215. Container = null;
  216. }
  217. }
  218. /// <summary>
  219. /// This class is for stubbing purposes only.
  220. /// </summary>
  221. internal sealed class RegistrationStub : IServiceRegistrar {
  222. public void Dispose() {
  223. }
  224. public void RegisterAll<Interface>() {
  225. throw new NotImplementedException();
  226. }
  227. public void Register<Interface>(Type implType) where Interface : class {
  228. throw new NotImplementedException();
  229. }
  230. public void Register<Interface, Implementation>() where Implementation : class, Interface {
  231. throw new NotImplementedException();
  232. }
  233. public void Register<Interface, Implementation>(string key) where Implementation : class, Interface {
  234. throw new NotImplementedException();
  235. }
  236. public void Register(string key, Type type) {
  237. throw new NotImplementedException();
  238. }
  239. public void Register(Type serviceType, Type implType) {
  240. throw new NotImplementedException();
  241. }
  242. public void Register(Type serviceType, Type implType, string key) {
  243. throw new NotImplementedException();
  244. }
  245. public void Register<Interface>(Interface instance) where Interface : class {
  246. throw new NotImplementedException();
  247. }
  248. public void Register<Interface>(Func<Interface> factoryMethod) where Interface : class {
  249. throw new NotImplementedException();
  250. }
  251. }
  252. }