PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/src/BurnSystems/src/Scope/Context.cs

https://bitbucket.org/mbrenn/entityconnector
C# | 299 lines | 166 code | 36 blank | 97 comment | 19 complexity | 709b554533f65839c611f617c05e9ecc MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using BurnSystems.Test;
  6. using BurnSystems.Logging;
  7. namespace BurnSystems.Scope
  8. {
  9. /// <summary>
  10. /// The context is the implementation of the <c>IContext</c> class.
  11. /// </summary>
  12. public class Context : IContext
  13. {
  14. /// <summary>
  15. /// Stores whether the context already had been disposed.
  16. /// </summary>
  17. private bool isDisposed;
  18. /// <summary>
  19. /// Stores the name of the context
  20. /// </summary>
  21. private string name;
  22. /// <summary>
  23. /// Stores the source
  24. /// </summary>
  25. private List<IContextSource> sources = new List<IContextSource> ();
  26. /// <summary>
  27. /// Stores the list of items
  28. /// </summary>
  29. private List<Item> items = new List<Item> ();
  30. /// <summary>
  31. /// Gets the name of the context
  32. /// </summary>
  33. public string Name {
  34. get { return this.name; }
  35. }
  36. /// <summary>
  37. /// Gets the local context source which can be used to add additional factory methods
  38. /// </summary>
  39. public IContextSource LocalContextSource {
  40. get {
  41. return this.sources.First ();
  42. }
  43. }
  44. /// <summary>
  45. /// Creates the context and everything is empty
  46. /// </summary>
  47. [Obsolete]
  48. internal Context ()
  49. {
  50. }
  51. /// <summary>
  52. /// Initializes a new instance of the <see cref="BurnSystems.Scope.Context"/> class.
  53. /// </summary>
  54. /// <param name='name'>
  55. /// Name of the context.
  56. /// </param>
  57. internal Context (string name)
  58. {
  59. this.name = name;
  60. }
  61. /// <summary>
  62. /// Initializes a new instance of the Context class
  63. /// </summary>
  64. /// <param name="source">Source of the context</param>
  65. [Obsolete]
  66. public Context (IContextSource source)
  67. {
  68. this.sources.Add (new ContextSource ("InnerContextSource"));
  69. Ensure.IsNotNull (source);
  70. this.sources.Add (source);
  71. }
  72. /// <summary>
  73. /// Initializes a new instance of the Context class
  74. /// </summary>
  75. /// <param name="source">Source of the context</param>
  76. /// <param name="name">Name of the context</param>
  77. public Context (IContextSource source, string name)
  78. {
  79. this.name = name;
  80. this.sources.Add (new ContextSource (name));
  81. Ensure.IsNotNull (source);
  82. this.sources.Add (source);
  83. }
  84. /// <summary>
  85. /// Creates a context not having a local context.
  86. /// This means that the request for LocalContextSource will return the original source
  87. /// </summary>
  88. /// <param name="source">Source to be used as local and global context</param>
  89. /// <returns>Context containing the required information</returns>
  90. [Obsolete]
  91. public static Context CreateWithoutLocalContext (IContextSource source)
  92. {
  93. return CreateWithoutLocalContext (source, "Unknown");
  94. }
  95. /// <summary>
  96. /// Creates a context not having a local context.
  97. /// This means that the request for LocalContextSource will return the original source
  98. /// </summary>
  99. /// <param name="source">Source to be used as local and global context</param>
  100. /// <param name="name">Name of the context</param>
  101. /// <returns>Context containing the required information</returns>
  102. public static Context CreateWithoutLocalContext (IContextSource source, string name)
  103. {
  104. Ensure.IsNotNull (source);
  105. var result = new Context (name);
  106. result.Add (source);
  107. return result;
  108. }
  109. /// <summary>
  110. /// Adds an item to context
  111. /// </summary>
  112. /// <param name="source">Source to be added</param>
  113. public void Add (IContextSource source)
  114. {
  115. Ensure.IsNotNull (source);
  116. if (this.sources.Any (x => x.Equals (source))) {
  117. // Already in
  118. return;
  119. }
  120. this.sources.Add (source);
  121. }
  122. /// <summary>
  123. /// Adds a contextsource created by the factory
  124. /// </summary>
  125. /// <param name="sourceFactory">Sourcefactory to be used</param>
  126. public void Add (IContextSourceFactory sourceFactory)
  127. {
  128. Ensure.IsNotNull (sourceFactory);
  129. this.Add (sourceFactory.CreateContextSource ());
  130. }
  131. /// <summary>
  132. /// Gets an object, it is created if necessary.
  133. /// This method only works, if there is just one
  134. /// instance within the context source
  135. /// </summary>
  136. /// <typeparam name="T">Type of the parameter</typeparam>
  137. /// <returns>Object to be created or retrieved</returns>
  138. public T Get<T> ()
  139. {
  140. if (this.isDisposed) {
  141. throw new ObjectDisposedException ("Context");
  142. }
  143. var found =
  144. this.items
  145. .Where (x => x.Value.GetType ().Equals (typeof(T)))
  146. .Select (x => x.Value)
  147. .Cast<T> ()
  148. .FirstOrDefault ();
  149. if (found == null) {
  150. found = this.sources
  151. .Select (x => x.Create<T> ())
  152. .Where (x => x != null)
  153. .FirstOrDefault ();
  154. if (found != null) {
  155. this.items.Add (
  156. new Item (found, string.Empty));
  157. }
  158. }
  159. return found;
  160. }
  161. /// <summary>
  162. /// Gets all object matching to a specific type
  163. /// </summary>
  164. /// <typeparam name="T"></typeparam>
  165. /// <returns>Enumeration of all items matching to the type</returns>
  166. public IEnumerable<T> GetAll<T> ()
  167. {
  168. if (this.isDisposed) {
  169. throw new ObjectDisposedException ("Context");
  170. }
  171. foreach (var item in this.items
  172. .Where(x => x.Value.GetType().Equals(typeof(T)))
  173. .Select(x => x.Value)
  174. .Cast<T>()) {
  175. yield return item;
  176. }
  177. // Go through all source
  178. foreach (var item in this.sources
  179. .SelectMany(x => x.CreateAll<T>())
  180. .Where(x => x != null)) {
  181. this.items.Add (
  182. new Item (item, string.Empty));
  183. yield return item;
  184. }
  185. }
  186. /// <summary>
  187. /// Gets an object by token. This object is created if necessary.
  188. /// </summary>
  189. /// <typeparam name="T">Type of the parameter</typeparam>
  190. /// <param name="token">Token to be added</param>
  191. /// <returns>Object to be created or retrieved</returns>
  192. public T Get<T> (string token)
  193. {
  194. if (this.isDisposed) {
  195. throw new ObjectDisposedException ("Context");
  196. }
  197. var found =
  198. this.items
  199. .Where (x => x.Token == token)
  200. .Cast<T> ()
  201. .FirstOrDefault ();
  202. if (found == null) {
  203. found = this.sources
  204. .Select (x => x.Create<T> (token))
  205. .Where (x => x != null)
  206. .FirstOrDefault ();
  207. if (found != null) {
  208. this.items.Add (
  209. new Item (found, token));
  210. }
  211. }
  212. return found;
  213. }
  214. /// <summary>
  215. /// Disposes all items implementing the IDisposable
  216. /// </summary>
  217. public void Dispose ()
  218. {
  219. if (this.isDisposed) {
  220. return;
  221. }
  222. var items = this.items.ToList ();
  223. this.items.Clear ();
  224. foreach (var item in items) {
  225. var disposable = item.Value as IDisposable;
  226. if (disposable != null) {
  227. disposable.Dispose ();
  228. }
  229. }
  230. this.isDisposed = true;
  231. }
  232. /// <summary>
  233. /// Stores the information
  234. /// </summary>
  235. private class Item
  236. {
  237. /// <summary>
  238. /// Initializes a new instance of the Item class.
  239. /// </summary>
  240. /// <param name="value">Item to be added</param>
  241. /// <param name="token">Token to be added</param>
  242. public Item (object value, string token)
  243. {
  244. this.Value = value;
  245. this.Token = token;
  246. }
  247. /// <summary>
  248. /// Gets or sets the item
  249. /// </summary>
  250. public object Value {
  251. get;
  252. set;
  253. }
  254. /// <summary>
  255. /// Gets or sets the token
  256. /// </summary>
  257. public string Token {
  258. get;
  259. set;
  260. }
  261. }
  262. }
  263. }