/nhibernate/src/NHibernate/Collection/Generic/PersistentGenericBag.cs

https://bitbucket.org/fabiomaulo/nhibernate/ · C# · 148 lines · 109 code · 20 blank · 19 comment · 5 complexity · d0e233ddd706fcad7c8e6932a9f6612a MD5 · raw file

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using NHibernate.DebugHelpers;
  6. using NHibernate.Engine;
  7. using NHibernate.Persister.Collection;
  8. namespace NHibernate.Collection.Generic
  9. {
  10. /// <summary>
  11. /// An unordered, unkeyed collection that can contain the same element
  12. /// multiple times. The .NET collections API, has no <c>Bag</c>.
  13. /// Most developers seem to use <see cref="IList{T}"/> to represent bag semantics,
  14. /// so NHibernate follows this practice.
  15. /// </summary>
  16. /// <typeparam name="T">The type of the element the bag should hold.</typeparam>
  17. /// <remarks>The underlying collection used is an <see cref="List{T}"/></remarks>
  18. [Serializable]
  19. [DebuggerTypeProxy(typeof (CollectionProxy<>))]
  20. public class PersistentGenericBag<T> : PersistentBag, IList<T>
  21. {
  22. // TODO NH: find a way to writeonce (no duplicated code from PersistentBag)
  23. /* NH considerations:
  24. * For various reason we know that the underlining type will be a List<T> or a
  25. * PersistentGenericBag<T>; in both cases the class implement all we need to don't duplicate
  26. * all code from PersistentBag.
  27. * In the explicit implementation of IList<T> we need to duplicate
  28. * code to take advantage from the better performance the use of generic implementation have
  29. * (mean .NET implementation of the underlining list).
  30. * In other cases, where PersistentBag use for example bag.Add, a cast, probably, is more
  31. * expensive than .NET original implementation.
  32. */
  33. private IList<T> gbag;
  34. public PersistentGenericBag() {}
  35. public PersistentGenericBag(ISessionImplementor session) : base(session) {}
  36. public PersistentGenericBag(ISessionImplementor session, ICollection<T> coll) : base(session, coll as ICollection)
  37. {
  38. gbag = coll as IList<T>;
  39. if (gbag == null)
  40. {
  41. List<T> l = new List<T>(coll);
  42. gbag = l;
  43. bag = l;
  44. }
  45. }
  46. protected IList<T> InternalBag
  47. {
  48. get { return gbag; }
  49. set
  50. {
  51. gbag = value;
  52. bag = (IList) gbag;
  53. }
  54. }
  55. public override void BeforeInitialize(ICollectionPersister persister, int anticipatedSize)
  56. {
  57. InternalBag = (IList<T>) persister.CollectionType.Instantiate(anticipatedSize);
  58. }
  59. #region IList<T> Members
  60. int IList<T>.IndexOf(T item)
  61. {
  62. Read();
  63. return gbag.IndexOf(item);
  64. }
  65. void IList<T>.Insert(int index, T item)
  66. {
  67. Write();
  68. gbag.Insert(index, item);
  69. }
  70. T IList<T>.this[int index]
  71. {
  72. get
  73. {
  74. Read();
  75. return gbag[index];
  76. }
  77. set
  78. {
  79. Write();
  80. gbag[index] = value;
  81. }
  82. }
  83. #endregion
  84. #region ICollection<T> Members
  85. void ICollection<T>.Add(T item)
  86. {
  87. if (!IsOperationQueueEnabled)
  88. {
  89. Write();
  90. gbag.Add(item);
  91. }
  92. else
  93. {
  94. QueueOperation(new SimpleAddDelayedOperation(this, item));
  95. }
  96. }
  97. bool ICollection<T>.Contains(T item)
  98. {
  99. bool? exists = ReadElementExistence(item);
  100. return !exists.HasValue ? gbag.Contains(item) : exists.Value;
  101. }
  102. void ICollection<T>.CopyTo(T[] array, int arrayIndex)
  103. {
  104. for (int i = arrayIndex; i < Count; i++)
  105. {
  106. array.SetValue(this[i], i);
  107. }
  108. }
  109. bool ICollection<T>.Remove(T item)
  110. {
  111. Initialize(true);
  112. bool result = gbag.Remove(item);
  113. if (result)
  114. {
  115. Dirty();
  116. }
  117. return result;
  118. }
  119. #endregion
  120. #region IEnumerable<T> Members
  121. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  122. {
  123. Read();
  124. return gbag.GetEnumerator();
  125. }
  126. #endregion
  127. }
  128. }