/src/Engine/MvcTurbine.Ninject/NinjectServiceLocator.cs

https://github.com/tyronegroves/mvcturbine · C# · 275 lines · 130 code · 36 blank · 109 comment · 9 complexity · ccf5bd6fa806e72aa80bc80f023953b7 MD5 · raw file

  1. namespace MvcTurbine.Ninject {
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using ComponentModel;
  6. using global::Ninject;
  7. /// <summary>
  8. /// Default implementation of the <seealso cref="IServiceLocator"/> contract with Ninject IoC.
  9. /// </summary>
  10. /// <remarks>
  11. /// To learn more about Ninject, please visit its website: http://ninject.org
  12. /// </remarks>
  13. [Serializable]
  14. public class NinjectServiceLocator : IServiceLocator, IServiceInjector {
  15. private TurbineModule currentModule;
  16. private static bool isDisposing;
  17. /// <summary>
  18. /// Default constructor. Locator is instantiated with a new <seealso cref="StandardKernel"/> instance.
  19. /// </summary>
  20. public NinjectServiceLocator() : this(new StandardKernel()) {
  21. }
  22. /// <summary>
  23. /// Creates an instance of the locator with the specified <seealso cref="IKernel"/>.
  24. /// </summary>
  25. /// <param name="kernel">Pre-defined <see cref="IKernel"/> to use within the container.</param>
  26. public NinjectServiceLocator(IKernel kernel) {
  27. if (kernel == null) {
  28. throw new ArgumentNullException("kernel", "The specified Ninject IKernel cannot be null.");
  29. }
  30. Container = kernel;
  31. }
  32. /// <summary>
  33. /// Gets the current <see cref="IKernel"/> associated with this instance.
  34. /// </summary>
  35. public IKernel Container { get; private set; }
  36. public IList<object> ResolveServices(Type type) {
  37. return Container.GetAll(type).ToList();
  38. }
  39. /// <summary>
  40. /// Gets the associated <see cref="IServiceRegistrar"/> to process.
  41. /// </summary>
  42. /// <returns></returns>
  43. public IServiceRegistrar Batch() {
  44. currentModule = new TurbineModule(Container);
  45. return currentModule;
  46. }
  47. /// <summary>
  48. /// Resolves the service of the specified type.
  49. /// </summary>
  50. /// <typeparam name="T">Type of service to resolve.</typeparam>
  51. /// <returns>An instance of the type, null otherwise.</returns>
  52. public T Resolve<T>() where T : class {
  53. try {
  54. return Container.Get<T>();
  55. }
  56. catch (ActivationException activationException) {
  57. return ResolveTheFirstBindingFromTheContainer(activationException, typeof(T)) as T;
  58. }
  59. catch (Exception ex) {
  60. throw new ServiceResolutionException(typeof(T), ex);
  61. }
  62. }
  63. /// <summary>
  64. /// Resolves the service of the specified type by the given string key.
  65. /// </summary>
  66. /// <typeparam name="T">Type of service to resolve.</typeparam>
  67. /// <param name="key">Unique key to distinguish the service.</param>
  68. /// <returns>An instance of the type, null otherwise.</returns>
  69. public T Resolve<T>(string key) where T : class {
  70. try {
  71. var value = Container.Get<T>(key);
  72. if (value == null) {
  73. throw new ServiceResolutionException(typeof(T));
  74. }
  75. return value;
  76. }
  77. catch (Exception ex) {
  78. throw new ServiceResolutionException(typeof(T), ex);
  79. }
  80. }
  81. /// <summary>
  82. /// Resolves the service of the specified type by the given type key.
  83. /// </summary>
  84. /// <typeparam name="T">Type of service to resolve.</typeparam>
  85. /// <param name="type">Key type of the service.</param>
  86. /// <returns>An instance of the type, null otherwise.</returns>
  87. public T Resolve<T>(Type type) where T : class {
  88. try {
  89. return Container.Get(type) as T;
  90. }
  91. catch (ActivationException activationException) {
  92. return ResolveTheFirstBindingFromTheContainer(activationException, typeof(T)) as T;
  93. }
  94. catch (Exception ex) {
  95. throw new ServiceResolutionException(type, ex);
  96. }
  97. }
  98. ///<summary>
  99. /// Resolves the service of the specified type by the given type key.
  100. ///</summary>
  101. ///<param name="type">Type of service to resolve.</param>
  102. ///<returns>An instance of the type, null otherwise</returns>
  103. public object Resolve(Type type) {
  104. try {
  105. return Container.Get(type);
  106. }
  107. catch (ActivationException activationException) {
  108. return ResolveTheFirstBindingFromTheContainer(activationException, type);
  109. }
  110. }
  111. /// <summary>
  112. /// Resolves the list of services of type <see cref="T"/> that are registered
  113. /// within the locator.
  114. /// </summary>
  115. /// <typeparam name="T">Type of the service to resolve.</typeparam>
  116. /// <returns>A list of service of type <see cref="T"/>, null otherwise.</returns>
  117. public IList<T> ResolveServices<T>() where T : class {
  118. return Container.GetAll<T>().ToList();
  119. }
  120. /// <summary>
  121. /// Registers the implemation type, <paramref name="implType"/>, with the locator under
  122. /// the <see cref="Interface"/> service type.
  123. /// </summary>
  124. /// <typeparam name="Interface">Type of the service to register.</typeparam>
  125. /// <param name="implType">Implementation type to use for registration.</param>
  126. public void Register<Interface>(Type implType) where Interface : class {
  127. currentModule.Register<Interface>(implType);
  128. }
  129. /// <summary>
  130. /// Registers the implemation type, <see cref="Implementation"/>, with the locator under
  131. /// the <see cref="Interface"/> service type.
  132. /// </summary>
  133. /// <typeparam name="Interface">Type of the service to register.</typeparam>
  134. /// <typeparam name="Implementation">Implementation type to use for registration.
  135. /// </typeparam>
  136. public void Register<Interface, Implementation>()
  137. where Implementation : class, Interface {
  138. currentModule.Register<Interface, Implementation>();
  139. }
  140. /// <summary>
  141. /// Registers the implemation type, <see cref="Implementation"/>, with the locator under
  142. /// the <see cref="Interface"/> service type.
  143. /// </summary>
  144. /// <typeparam name="Interface">Type of the service to register.</typeparam>
  145. /// <typeparam name="Implementation">Implementation type to use for registration.
  146. /// </typeparam>
  147. /// <param name="key">Unique key to distinguish the service.</param>
  148. public void Register<Interface, Implementation>(string key)
  149. where Implementation : class, Interface {
  150. currentModule.Register<Interface, Implementation>(key);
  151. }
  152. /// <summary>
  153. /// Registers the implementation type, <paramref name="type"/>, with the locator
  154. /// by the given string key.
  155. /// </summary>
  156. /// <param name="key">Unique key to distinguish the service.</param>
  157. /// <param name="type">Implementation type to use.</param>
  158. public void Register(string key, Type type) {
  159. currentModule.Register(key, type);
  160. }
  161. /// <summary>
  162. /// See <see cref="IServiceLocator.Register(System.Type,System.Type)"/>.
  163. /// </summary>
  164. /// <param name="serviceType"></param>
  165. /// <param name="implType"></param>
  166. public void Register(Type serviceType, Type implType) {
  167. currentModule.Register(serviceType, implType);
  168. }
  169. /// <summary>
  170. /// See <see cref="IServiceLocator.Register(System.Type,System.Type, System.String)"/>.
  171. /// </summary>
  172. /// <param name="serviceType"></param>
  173. /// <param name="implType"></param>
  174. /// <param name="key"></param>
  175. public void Register(Type serviceType, Type implType, string key) {
  176. currentModule.Register(serviceType, implType, key);
  177. }
  178. /// <summary>
  179. /// See <see cref="IServiceLocator.Register{Interface}(Interface)"/>.
  180. /// </summary>
  181. /// <typeparam name="Interface"></typeparam>
  182. /// <param name="instance"></param>
  183. public void Register<Interface>(Interface instance) where Interface : class {
  184. currentModule.Register(instance);
  185. }
  186. /// <summary>
  187. /// Resolves the service of the specified interface with the provided factory method.
  188. /// </summary>
  189. /// <typeparam name="Interface"></typeparam>
  190. /// <param name="factoryMethod"></param>
  191. public void Register<Interface>(Func<Interface> factoryMethod) where Interface : class {
  192. currentModule.Register(factoryMethod);
  193. }
  194. /// <summary>
  195. /// Resolves the service of the specified interface with the provided factory method.
  196. /// </summary>
  197. /// <param name="factoryMethod">The factory method which will be used to resolve this interface.</param>
  198. /// <returns>An instance of the type, null otherwise</returns>
  199. public TService Inject<TService>(TService instance) where TService : class {
  200. Container.Inject(instance);
  201. return instance;
  202. }
  203. public void TearDown<TService>(TService instance) where TService : class {
  204. }
  205. /// <summary>
  206. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  207. /// </summary>
  208. /// <filterpriority>2</filterpriority>
  209. public void Dispose() {
  210. // If we're in the process of disposing, return
  211. if (isDisposing) return;
  212. if (Container == null) return;
  213. // Signal the fact that we're disposing the container
  214. isDisposing = true;
  215. // Perform actual dispose
  216. Container.Dispose();
  217. // Clean up these pieces
  218. Container = null;
  219. currentModule = null;
  220. }
  221. #region Handle Activation Exception
  222. private object ResolveTheFirstBindingFromTheContainer(Exception activationException, Type type) {
  223. var firstBinding = GetNameOfFirstBinding(type);
  224. if (firstBinding.BindingExists)
  225. return Container.Get(type, firstBinding.Name);
  226. throw new ServiceResolutionException(type, activationException);
  227. }
  228. private FirstBindingInfo GetNameOfFirstBinding(Type type) {
  229. var binding = Container.GetBindings(type).OrderBy(x => x.Metadata.Name).FirstOrDefault();
  230. return binding == null ? new FirstBindingInfo { BindingExists = false } :
  231. new FirstBindingInfo { BindingExists = true, Name = binding.Metadata.Name };
  232. }
  233. private class FirstBindingInfo {
  234. public string Name { get; set; }
  235. public bool BindingExists { get; set; }
  236. }
  237. #endregion
  238. }
  239. }