/src/NHibernate/Type/ArrayType.cs

https://github.com/whut/nhibernate-core · C# · 165 lines · 106 code · 19 blank · 40 comment · 9 complexity · ce63054a289ce144b939ebc5608b3d21 MD5 · raw file

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using NHibernate.Collection;
  6. using NHibernate.Engine;
  7. using NHibernate.Persister.Collection;
  8. using NHibernate.Util;
  9. namespace NHibernate.Type
  10. {
  11. /// <summary>
  12. /// An <see cref="IType"/> that maps an <see cref="Array"/> collection
  13. /// to the database.
  14. /// </summary>
  15. [Serializable]
  16. public class ArrayType : CollectionType
  17. {
  18. private readonly System.Type elementClass;
  19. private readonly System.Type arrayClass;
  20. /// <summary>
  21. /// Initializes a new instance of a <see cref="ArrayType"/> class for
  22. /// a specific role.
  23. /// </summary>
  24. /// <param name="role">The role the persistent collection is in.</param>
  25. /// <param name="propertyRef">The name of the property in the
  26. /// owner object containing the collection ID, or <see langword="null" /> if it is
  27. /// the primary key.</param>
  28. /// <param name="elementClass">The <see cref="System.Type"/> of the element contained in the array.</param>
  29. /// <param name="isEmbeddedInXML"></param>
  30. /// <remarks>
  31. /// This creates a bag that is non-generic.
  32. /// </remarks>
  33. public ArrayType(string role, string propertyRef, System.Type elementClass, bool isEmbeddedInXML)
  34. : base(role, propertyRef, isEmbeddedInXML)
  35. {
  36. this.elementClass = elementClass;
  37. arrayClass = Array.CreateInstance(elementClass, 0).GetType();
  38. }
  39. /// <summary>
  40. /// The <see cref="System.Array"/> for the element.
  41. /// </summary>
  42. public override System.Type ReturnedClass
  43. {
  44. get { return arrayClass; }
  45. }
  46. public override IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister, object key)
  47. {
  48. return new PersistentArrayHolder(session, persister);
  49. }
  50. /// <summary>
  51. ///
  52. /// </summary>
  53. /// <param name="st"></param>
  54. /// <param name="value"></param>
  55. /// <param name="index"></param>
  56. /// <param name="session"></param>
  57. public override void NullSafeSet(IDbCommand st, object value, int index, ISessionImplementor session)
  58. {
  59. base.NullSafeSet(st, session.PersistenceContext.GetCollectionHolder(value), index, session);
  60. }
  61. public override IEnumerable GetElementsIterator(object collection)
  62. {
  63. return (Array)collection;
  64. }
  65. /// <summary>
  66. /// Wraps a <see cref="System.Array"/> in a <see cref="PersistentArrayHolder"/>.
  67. /// </summary>
  68. /// <param name="session">The <see cref="ISessionImplementor"/> for the collection to be a part of.</param>
  69. /// <param name="array">The unwrapped array.</param>
  70. /// <returns>
  71. /// An <see cref="PersistentArrayHolder"/> that wraps the non NHibernate <see cref="System.Array"/>.
  72. /// </returns>
  73. public override IPersistentCollection Wrap(ISessionImplementor session, object array)
  74. {
  75. return new PersistentArrayHolder(session, array);
  76. }
  77. /// <summary></summary>
  78. public override bool IsArrayType
  79. {
  80. get { return true; }
  81. }
  82. // Not ported - ToString( object value, ISessionFactoryImplementor factory )
  83. // - PesistentCollectionType implementation is able to handle arrays too in .NET
  84. public override object InstantiateResult(object original)
  85. {
  86. return Array.CreateInstance(elementClass, ((Array) original).Length);
  87. }
  88. public override object Instantiate(int anticipatedSize)
  89. {
  90. throw new NotSupportedException();
  91. }
  92. public override bool HasHolder(EntityMode entityMode)
  93. {
  94. return true;
  95. }
  96. public override object IndexOf(object collection, object element)
  97. {
  98. Array array = (Array) collection;
  99. int length = array.Length;
  100. for (int i = 0; i < length; i++)
  101. {
  102. //TODO: proxies!
  103. if (array.GetValue(i) == element)
  104. return i;
  105. }
  106. return null;
  107. }
  108. protected internal override bool InitializeImmediately(EntityMode entityMode)
  109. {
  110. return true;
  111. }
  112. public override object ReplaceElements(object original, object target, object owner, IDictionary copyCache, ISessionImplementor session)
  113. {
  114. Array org = (Array) original;
  115. Array result = (Array)target;
  116. int length = org.Length;
  117. if (length != result.Length)
  118. {
  119. //note: this affects the return value!
  120. result = (Array) InstantiateResult(original);
  121. }
  122. IType elemType = GetElementType(session.Factory);
  123. for (int i = 0; i < length; i++)
  124. {
  125. result.SetValue(elemType.Replace(org.GetValue(i), null, session, owner, copyCache), i);
  126. }
  127. return result;
  128. }
  129. public override string ToLoggableString(object value, ISessionFactoryImplementor factory)
  130. {
  131. if (value == null)
  132. {
  133. return "null";
  134. }
  135. Array array = (Array) value;
  136. int length = array.Length;
  137. IList list = new List<object>(length);
  138. IType elemType = GetElementType(factory);
  139. for (int i = 0; i < length; i++)
  140. {
  141. list.Add(elemType.ToLoggableString(array.GetValue(i), factory));
  142. }
  143. return CollectionPrinter.ToString(list);
  144. }
  145. }
  146. }