/src/LinFu.IoC/ServiceContainer.cs

http://github.com/philiplaureano/LinFu · C# · 192 lines · 71 code · 23 blank · 98 comment · 18 complexity · bcef616fc80bea25210511c0ac3e8b3c MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Security;
  4. using LinFu.IoC.Interfaces;
  5. namespace LinFu.IoC
  6. {
  7. /// <summary>
  8. /// Represents a service container with additional
  9. /// extension points for customizing service instances
  10. /// </summary>
  11. [SecurityCritical]
  12. public class ServiceContainer : IServiceContainer
  13. {
  14. private readonly IGetService _getServiceBehavior;
  15. private readonly List<IPostProcessor> _postProcessors = new List<IPostProcessor>();
  16. private readonly List<IPreProcessor> _preprocessors = new List<IPreProcessor>();
  17. /// <summary>
  18. /// Initializes the container with the default services.
  19. /// </summary>
  20. public ServiceContainer()
  21. {
  22. _getServiceBehavior = new DefaultGetServiceBehavior(this);
  23. this.AddDefaultServices();
  24. }
  25. /// <summary>
  26. /// Initializes the container with a custom <see cref="ICreateInstance" /> type.
  27. /// </summary>
  28. /// <param name="getServiceBehavior">The instance that will be responsible for generating service instances.</param>
  29. /// <param name="factoryStorage">
  30. /// The <see cref="IFactoryStorage" /> instance responsible for determining which factory
  31. /// instance will instantiate a given service request.
  32. /// </param>
  33. public ServiceContainer(IGetService getServiceBehavior, IFactoryStorage factoryStorage)
  34. {
  35. if (getServiceBehavior == null)
  36. throw new ArgumentNullException("getServiceBehavior");
  37. if (factoryStorage == null)
  38. throw new ArgumentNullException("factoryStorage");
  39. _getServiceBehavior = getServiceBehavior;
  40. FactoryStorage = factoryStorage;
  41. this.AddDefaultServices();
  42. }
  43. /// <summary>
  44. /// Gets the value indicating the <see cref="IFactoryStorage" /> instance
  45. /// that will be used to store each <see cref="IFactory" /> instance.
  46. /// </summary>
  47. internal IFactoryStorage FactoryStorage { get; } = new FactoryStorage();
  48. /// <summary>
  49. /// Gets or sets a <see cref="bool">System.Boolean</see> value
  50. /// that determines whether or not the container should throw
  51. /// a <see cref="ServiceNotFoundException" /> if a requested service
  52. /// cannot be found or created.
  53. /// </summary>
  54. public virtual bool SuppressErrors { get; set; }
  55. /// <summary>
  56. /// Adds an <see cref="IFactory" /> instance and associates it
  57. /// with the given <paramref name="serviceType">service type</paramref> and
  58. /// <paramref name="serviceName">service name</paramref>.
  59. /// </summary>
  60. /// <param name="serviceName">The name of the service to associate with the given <see cref="IFactory" /> instance.</param>
  61. /// <param name="serviceType">The type of service that the factory will be able to create.</param>
  62. /// <param name="additionalParameterTypes">The list of additional parameters that this factory type will support.</param>
  63. /// <param name="factory">The <see cref="IFactory" /> instance that will create the object instance.</param>
  64. public virtual void AddFactory(string serviceName, Type serviceType, IEnumerable<Type> additionalParameterTypes,
  65. IFactory factory)
  66. {
  67. FactoryStorage.AddFactory(serviceName, serviceType, additionalParameterTypes, factory);
  68. }
  69. /// <summary>
  70. /// Adds an <see cref="IFactory" /> instance and associates it
  71. /// with the given <paramref name="serviceType">service type</paramref>.
  72. /// </summary>
  73. /// <param name="serviceType">The service type to associate with the factory</param>
  74. /// <param name="additionalParameterTypes">The list of additional parameters that this factory type will support.</param>
  75. /// <param name="factory">The <see cref="IFactory" /> instance that will be responsible for creating the service instance</param>
  76. public virtual void AddFactory(Type serviceType, IEnumerable<Type> additionalParameterTypes, IFactory factory)
  77. {
  78. AddFactory(null, serviceType, additionalParameterTypes, factory);
  79. }
  80. /// <summary>
  81. /// Determines whether or not the given <paramref name="serviceType" />
  82. /// can be instantiated by the container.
  83. /// </summary>
  84. /// <param name="serviceType">The type of service to instantiate.</param>
  85. /// <param name="additionalParameterTypes">The list of additional parameters that this factory type will support.</param>
  86. /// <returns>Returns <c>true</c> if the service exists; otherwise, it will return <c>false</c>.</returns>
  87. public virtual bool Contains(Type serviceType, IEnumerable<Type> additionalParameterTypes)
  88. {
  89. return Contains(null, serviceType, additionalParameterTypes);
  90. }
  91. /// <summary>
  92. /// Overridden. Causes the container to instantiate the service with the given
  93. /// <paramref name="serviceType">service type</paramref>. If the service type cannot be created, then an
  94. /// exception will be thrown if the <see cref="IContainer.SuppressErrors" /> property
  95. /// is set to false. Otherwise, it will simply return null.
  96. /// </summary>
  97. /// <remarks>
  98. /// This overload of the <c>GetService</c> method has been overridden
  99. /// so that its results can be handled by the postprocessors.
  100. /// </remarks>
  101. /// <seealso cref="IPostProcessor" />
  102. /// <param name="serviceType">The service type to instantiate.</param>
  103. /// <param name="additionalArguments">The additional arguments that will be used to instantiate the service type.</param>
  104. /// <returns>
  105. /// If successful, it will return a service instance that is compatible with the given type;
  106. /// otherwise, it will just return a null value.
  107. /// </returns>
  108. public virtual object GetService(Type serviceType, params object[] additionalArguments)
  109. {
  110. return GetService(null, serviceType, additionalArguments);
  111. }
  112. /// <summary>
  113. /// Causes the container to instantiate the service with the given
  114. /// <paramref name="serviceType">service type</paramref>. If the service type cannot be created, then an
  115. /// exception will be thrown if the <see cref="IContainer.SuppressErrors" /> property
  116. /// is set to false. Otherwise, it will simply return null.
  117. /// </summary>
  118. /// <param name="serviceName">The name of the service to instantiate.</param>
  119. /// <param name="serviceType">The service type to instantiate.</param>
  120. /// <param name="additionalArguments">The additional arguments that will be used to instantiate the service type.</param>
  121. /// <returns>
  122. /// If successful, it will return a service instance that is compatible with the given type;
  123. /// otherwise, it will just return a <c>null</c> value.
  124. /// </returns>
  125. public virtual object GetService(string serviceName, Type serviceType, params object[] additionalArguments)
  126. {
  127. IFactory factory = null;
  128. if (FactoryStorage != null)
  129. factory = FactoryStorage.GetFactory(serviceName, serviceType, additionalArguments);
  130. var serviceRequest = new ServiceRequest(serviceName, serviceType, additionalArguments, factory, this);
  131. var instance = _getServiceBehavior.GetService(serviceRequest);
  132. if (SuppressErrors == false && instance == null && serviceName == null)
  133. throw new ServiceNotFoundException(serviceType);
  134. if (SuppressErrors == false && instance == null && serviceName != null)
  135. throw new NamedServiceNotFoundException(serviceName, serviceType);
  136. return instance;
  137. }
  138. /// <summary>
  139. /// Determines whether or not a service can be created using
  140. /// the given <paramref name="serviceName">service name</paramref>
  141. /// and <paramref name="serviceType">service type</paramref>.
  142. /// </summary>
  143. /// <param name="serviceName">The name of the service to associate with the given <see cref="IFactory" /> instance.</param>
  144. /// <param name="serviceType">The type of service that the factory will be able to create.</param>
  145. /// <param name="additionalParameterTypes">The list of additional parameters that this factory type will support.</param>
  146. /// <returns>Returns <c>true</c> if the service exists; otherwise, it will return <c>false</c>.</returns>
  147. public virtual bool Contains(string serviceName, Type serviceType, IEnumerable<Type> additionalParameterTypes)
  148. {
  149. return FactoryStorage.ContainsFactory(serviceName, serviceType, additionalParameterTypes);
  150. }
  151. /// <summary>
  152. /// The list of postprocessors that will handle every
  153. /// service request result.
  154. /// </summary>
  155. public virtual IList<IPostProcessor> PostProcessors => _postProcessors;
  156. /// <summary>
  157. /// The list of preprocessors that will handle
  158. /// every service request before each actual service is created.
  159. /// </summary>
  160. public virtual IList<IPreProcessor> PreProcessors
  161. {
  162. get { return _preprocessors; }
  163. }
  164. /// <summary>
  165. /// The list of services currently available inside the container.
  166. /// </summary>
  167. public virtual IEnumerable<IServiceInfo> AvailableServices => FactoryStorage.AvailableFactories;
  168. }
  169. }