PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Lyh.FrameWork/FrameWork/ModularAndPlugin/Core/Composition/Composer.cs

http://AngleCode.codeplex.com
C# | 253 lines | 140 code | 28 blank | 85 comment | 29 complexity | 0f776f9b2ccfc4e8e164a4f891afe11f MD5 | raw file
  1. namespace ModularAndPlugin.Core.Composition
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.ComponentModel.Composition;
  6. using System.ComponentModel.Composition.Hosting;
  7. using System.ComponentModel.Composition.Primitives;
  8. using System.Linq;
  9. /// <summary>
  10. /// Provides a common mechanism for composing parts.
  11. /// </summary>
  12. public class Composer
  13. {
  14. #region Fields
  15. private bool modified;
  16. private readonly IDictionary<ExportProvider, Action<ExportProvider, CompositionContainer>> postContainerModifiers =
  17. new Dictionary<ExportProvider, Action<ExportProvider, CompositionContainer>>();
  18. #endregion
  19. #region Constructor
  20. /// <summary>
  21. /// Initialises a new instance of <see cref="Composer" />.
  22. /// </summary>
  23. public Composer()
  24. {
  25. ExportProviders = new List<ExportProvider>();
  26. }
  27. #endregion
  28. #region Properties
  29. /// <summary>
  30. /// Gets the catalog to use for composition.
  31. /// </summary>
  32. public ComposablePartCatalog Catalog { get; private set; }
  33. /// <summary>
  34. /// Gets the container to use for composition.
  35. /// </summary>
  36. public CompositionContainer Container { get; private set; }
  37. /// <summary>
  38. /// Gets the export provider to use for composition.
  39. /// </summary>
  40. public IList<ExportProvider> ExportProviders { get; private set; }
  41. #endregion
  42. #region Methods
  43. /// <summary>
  44. /// Adds the specified catalog to the composer.
  45. /// </summary>
  46. /// <param name="catalog">The catalog to add to the composer.</param>
  47. public void AddCatalog(ComposablePartCatalog catalog)
  48. {
  49. if (catalog == null)
  50. throw new ArgumentNullException("catalog");
  51. if (Catalog == null)
  52. Catalog = catalog;
  53. else
  54. {
  55. var aggregate = Catalog as AggregateCatalog;
  56. if (aggregate != null)
  57. aggregate.Catalogs.Add(catalog);
  58. else
  59. {
  60. aggregate = new AggregateCatalog();
  61. aggregate.Catalogs.Add(Catalog);
  62. aggregate.Catalogs.Add(catalog);
  63. Catalog = aggregate;
  64. }
  65. }
  66. modified = true;
  67. }
  68. /// <summary>
  69. /// Adds the specific export provider to the composer.
  70. /// </summary>
  71. /// <param name="provider">The export provider add to the composer.</param>
  72. /// <param name="postContainerModifier">A modifier action called after the container has been created.</param>
  73. public void AddExportProvider(ExportProvider provider, Action<ExportProvider, CompositionContainer> postContainerModifier = null)
  74. {
  75. if (provider == null)
  76. throw new ArgumentNullException("provider");
  77. ExportProviders.Add(provider);
  78. if (postContainerModifier != null)
  79. postContainerModifiers.Add(provider, postContainerModifier);
  80. }
  81. /// <summary>
  82. /// Composes the specified object.
  83. /// </summary>
  84. /// <param name="object">The object to be composed.</param>
  85. public void Compose(object @object)
  86. {
  87. if (@object == null)
  88. throw new ArgumentNullException("object");
  89. if (Catalog == null)
  90. return;
  91. EnsureContainer();
  92. Container.ComposeParts(@object);
  93. }
  94. /// <summary>
  95. /// Composes the specified object.
  96. /// </summary>
  97. /// <param name="object">The object to be composed.</param>
  98. public void ComposeWithNullCatalog(object @object)
  99. {
  100. if (@object == null)
  101. throw new ArgumentNullException("object");
  102. //if (Catalog == null)
  103. // return;
  104. EnsureContainer();
  105. Container.ComposeParts(@object);
  106. }
  107. /// <summary>
  108. /// Gets an instance of the specified type from the <see cref="Composer" />.
  109. /// </summary>
  110. /// <typeparam name="T">The type of instance to resolve.</typeparam>
  111. /// <returns>The resolved instance.</returns>
  112. public T Resolve<T>()
  113. {
  114. return Resolve<T>(null);
  115. }
  116. /// <summary>
  117. /// Gets an instance of the specified type from the <see cref="Composer" />.
  118. /// </summary>
  119. /// <typeparam name="T">The type of instance to resolve.</typeparam>
  120. /// <param name="contractName">The contract name the type was exported with.</param>
  121. /// <returns>The resolved instance.</returns>
  122. public T Resolve<T>(string contractName)
  123. {
  124. if (Catalog == null)
  125. return default(T);
  126. EnsureContainer();
  127. return (string.IsNullOrEmpty(contractName))
  128. ? Container.GetExportedValue<T>()
  129. : Container.GetExportedValue<T>(contractName);
  130. }
  131. /// <summary>
  132. /// Gets an instance of <see cref="Lazy{T,TMetadata}" /> for the specified trip from the <see cref="Composer" />.
  133. /// </summary>
  134. /// <typeparam name="T">The type of instance to resolve.</typeparam>
  135. /// <typeparam name="TMetadata">The metadata type to resolve.</typeparam>
  136. /// <returns>A <see cref="Lazy{T,TMetadata}" /> that allows lazy-loading.</returns>
  137. public Lazy<T, TMetadata> Resolve<T, TMetadata>()
  138. {
  139. return Resolve<T, TMetadata>(null);
  140. }
  141. /// <summary>
  142. /// Gets an instance of <see cref="Lazy{T,TMetadata}" /> for the specified trip from the <see cref="Composer" />.
  143. /// </summary>
  144. /// <typeparam name="T">The type of instance to resolve.</typeparam>
  145. /// <typeparam name="TMetadata">The metadata type to resolve.</typeparam>
  146. /// <param name="contractName">The contract name the type was exported with.</param>
  147. /// <returns>A <see cref="Lazy{T,TMetadata}" /> that allows lazy-loading.</returns>
  148. public Lazy<T, TMetadata> Resolve<T, TMetadata>(string contractName)
  149. {
  150. if (Catalog == null)
  151. return null;
  152. EnsureContainer();
  153. return (string.IsNullOrEmpty(contractName))
  154. ? Container.GetExport<T, TMetadata>()
  155. : Container.GetExport<T, TMetadata>(contractName);
  156. }
  157. /// <summary>
  158. /// Gets all instances of the specified type from the <see cref="Composer" />.
  159. /// </summary>
  160. /// <typeparam name="T">The type of instance to resolve.</typeparam>
  161. /// <returns>An enumerable of resolved instances.</returns>
  162. public IEnumerable<T> ResolveAll<T>()
  163. {
  164. return ResolveAll<T>(null);
  165. }
  166. /// <summary>
  167. /// Gets all instances of the specified type from the <see cref="Composer" />.
  168. /// </summary>
  169. /// <typeparam name="T">The type of instance to resolve.</typeparam>
  170. /// <param name="contractName">The contract name the type was exported with.</param>
  171. /// <returns>An enumerable of resolved instances.</returns>
  172. public IEnumerable<T> ResolveAll<T>(string contractName)
  173. {
  174. if (Catalog == null)
  175. return new T[0];
  176. EnsureContainer();
  177. return (string.IsNullOrEmpty(contractName))
  178. ? Container.GetExportedValues<T>()
  179. : Container.GetExportedValues<T>(contractName);
  180. }
  181. /// <summary>
  182. /// Gets all instances of <see cref="Lazy{T,TMetadata}" /> of the specified type from the <see cref="Composer" />.
  183. /// </summary>
  184. /// <typeparam name="T">The type of instance to resolve.</typeparam>
  185. /// <typeparam name="TMetadata">The metadata type to resolve.</typeparam>
  186. /// <returns>An enumerable of <see cref="Lazy{T,TMetadata}" />.</returns>
  187. public IEnumerable<Lazy<T, TMetadata>> ResolveAll<T, TMetadata>()
  188. {
  189. return ResolveAll<T, TMetadata>(null);
  190. }
  191. /// <summary>
  192. /// Gets all instances of <see cref="Lazy{T,TMetadata}" /> of the specified type from the <see cref="Composer" />.
  193. /// </summary>
  194. /// <typeparam name="T">The type of instance to resolve.</typeparam>
  195. /// <typeparam name="TMetadata">The metadata type to resolve.</typeparam>
  196. /// <param name="contractName">The contract name the type was exported with.</param>
  197. /// <returns>An enumerable of <see cref="Lazy{T,TMetadata}" />.</returns>
  198. public IEnumerable<Lazy<T, TMetadata>> ResolveAll<T, TMetadata>(string contractName)
  199. {
  200. if (Catalog == null)
  201. return null;
  202. EnsureContainer();
  203. return (string.IsNullOrEmpty(contractName))
  204. ? Container.GetExports<T, TMetadata>()
  205. : Container.GetExports<T, TMetadata>(contractName);
  206. }
  207. /// <summary>
  208. /// Ensures the Container has been instantiated/re-instantiated if the Composer has been modified.
  209. /// </summary>
  210. private void EnsureContainer()
  211. {
  212. if (modified || Container == null)
  213. {
  214. if (Container != null)
  215. Container.Dispose();
  216. Container = new CompositionContainer(Catalog, ExportProviders.ToArray());
  217. foreach (var provider in postContainerModifiers.Keys)
  218. postContainerModifiers[provider](provider, Container);
  219. Container.ComposeExportedValue(this);
  220. modified = false;
  221. }
  222. }
  223. #endregion
  224. }
  225. }