sqlser.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SqlSer.cs" company="Microsoft Corporation">
  3. // Copyright (c) Microsoft Corporation. All Rights Reserved.
  4. // Information Contained Herein is Proprietary and Confidential.
  5. // </copyright>
  6. // <owner current="true" primary="true">[....]</owner>
  7. // <owner current="true" primary="true">[....]</owner>
  8. // <owner current="true" primary="true">daltudov</owner>
  9. // <owner current="true" primary="true">[....]</owner>
  10. // <owner current="true" primary="false">beysims</owner>
  11. // <owner current="true" primary="false">[....]</owner>
  12. // <owner current="true" primary="false">vadimt</owner>
  13. // <owner current="false" primary="false">venkar</owner>
  14. // <owner current="false" primary="false">[....]</owner>
  15. //------------------------------------------------------------------------------
  16. using System;
  17. using System.Collections;
  18. using System.Data;
  19. using System.Data.Common;
  20. using System.Data.Sql;
  21. using System.Data.SqlClient;
  22. using System.Data.SqlTypes;
  23. using System.IO;
  24. using System.Reflection;
  25. using System.Reflection.Emit;
  26. using System.Runtime.InteropServices;
  27. using System.Runtime.Serialization;
  28. using System.Runtime.Serialization.Formatters.Binary;
  29. using System.Text;
  30. using System.Runtime.CompilerServices;
  31. namespace Microsoft.SqlServer.Server {
  32. internal class SerializationHelperSql9 {
  33. // Don't let anyone create an instance of this class.
  34. private SerializationHelperSql9() {}
  35. // Get the m_size of the serialized stream for this type, in bytes.
  36. // This method creates an instance of the type using the public
  37. // no-argument constructor, serializes it, and returns the m_size
  38. // in bytes.
  39. // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set.
  40. [MethodImpl(MethodImplOptions.NoInlining)]
  41. internal static int SizeInBytes(Type t) {
  42. return SizeInBytes(Activator.CreateInstance(t));
  43. }
  44. // Get the m_size of the serialized stream for this type, in bytes.
  45. internal static int SizeInBytes(object instance) {
  46. Type t = instance.GetType();
  47. Format k = GetFormat(t);
  48. DummyStream stream = new DummyStream();
  49. Serializer ser = GetSerializer(instance.GetType());
  50. ser.Serialize(stream, instance);
  51. return (int) stream.Length;
  52. }
  53. internal static void Serialize(Stream s, object instance) {
  54. GetSerializer(instance.GetType()).Serialize(s, instance);
  55. }
  56. internal static object Deserialize(Stream s, Type resultType) {
  57. return GetSerializer(resultType).Deserialize(s);
  58. }
  59. private static Format GetFormat(Type t) {
  60. return GetUdtAttribute(t).Format;
  61. }
  62. //cache the relationship between a type and its serializer
  63. //this is expensive to compute since it involves traversing the
  64. //custom attributes of the type using reflection.
  65. //
  66. //use a per-thread cache, so that there are no synchronization
  67. //issues when accessing cache entries from multiple threads.
  68. [ThreadStatic]
  69. private static Hashtable m_types2Serializers;
  70. private static Serializer GetSerializer(Type t) {
  71. if (m_types2Serializers == null)
  72. m_types2Serializers = new Hashtable();
  73. Serializer s = (Serializer) m_types2Serializers[t];
  74. if (s == null) {
  75. s = (Serializer) GetNewSerializer(t);
  76. m_types2Serializers[t] = s;
  77. }
  78. return s;
  79. }
  80. internal static int GetUdtMaxLength(Type t) {
  81. SqlUdtInfo udtInfo = SqlUdtInfo.GetFromType(t);
  82. if (Format.Native == udtInfo.SerializationFormat) {
  83. //In the native format, the user does not specify the
  84. //max byte size, it is computed from the type definition
  85. return SerializationHelperSql9.SizeInBytes(t);
  86. }
  87. else {
  88. //In all other formats, the user specifies the maximum size in bytes.
  89. return udtInfo.MaxByteSize;
  90. }
  91. }
  92. private static object[] GetCustomAttributes (Type t) {
  93. return t.GetCustomAttributes(typeof(SqlUserDefinedTypeAttribute), false);
  94. }
  95. internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) {
  96. SqlUserDefinedTypeAttribute udtAttr = null;
  97. object[] attr = GetCustomAttributes (t);
  98. if (attr != null && attr.Length == 1) {
  99. udtAttr = (SqlUserDefinedTypeAttribute) attr[0];
  100. }
  101. else {
  102. throw InvalidUdtException.Create(t, Res.SqlUdtReason_NoUdtAttribute);
  103. }
  104. return udtAttr;
  105. }
  106. // Create a new serializer for the given type.
  107. private static Serializer GetNewSerializer(Type t) {
  108. SqlUserDefinedTypeAttribute udtAttr = GetUdtAttribute(t);
  109. Format k = GetFormat(t);
  110. switch (k) {
  111. case Format.Native:
  112. return new NormalizedSerializer(t);
  113. case Format.UserDefined:
  114. return new BinarySerializeSerializer(t);
  115. case Format.Unknown: // should never happen, but fall through
  116. default:
  117. throw ADP.InvalidUserDefinedTypeSerializationFormat(k);
  118. }
  119. }
  120. }
  121. // The base serializer class.
  122. internal abstract class Serializer {
  123. public abstract object Deserialize(Stream s);
  124. public abstract void Serialize(Stream s, object o);
  125. protected Type m_type;
  126. protected Serializer(Type t) {
  127. this.m_type = t;
  128. }
  129. }
  130. internal sealed class NormalizedSerializer: Serializer {
  131. BinaryOrderedUdtNormalizer m_normalizer;
  132. bool m_isFixedSize;
  133. int m_maxSize;
  134. internal NormalizedSerializer(Type t): base(t) {
  135. SqlUserDefinedTypeAttribute udtAttr = SerializationHelperSql9.GetUdtAttribute(t);
  136. this.m_normalizer = new BinaryOrderedUdtNormalizer(t, true);
  137. this.m_isFixedSize = udtAttr.IsFixedLength;
  138. this.m_maxSize = this.m_normalizer.Size;
  139. }
  140. public override void Serialize(Stream s, object o) {
  141. m_normalizer.NormalizeTopObject(o, s);
  142. }
  143. public override object Deserialize(Stream s) {
  144. object result = m_normalizer.DeNormalizeTopObject(this.m_type, s);
  145. return result;
  146. }
  147. }
  148. internal sealed class BinarySerializeSerializer: Serializer {
  149. internal BinarySerializeSerializer(Type t): base(t) {
  150. }
  151. public override void Serialize(Stream s, object o) {
  152. BinaryWriter w = new BinaryWriter(s);
  153. ((IBinarySerialize)o).Write(w);
  154. }
  155. // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set.
  156. [MethodImpl(MethodImplOptions.NoInlining)]
  157. public override object Deserialize(Stream s) {
  158. object instance = Activator.CreateInstance(m_type);
  159. BinaryReader r = new BinaryReader(s);
  160. ((IBinarySerialize)instance).Read(r);
  161. return instance;
  162. }
  163. }
  164. // A dummy stream class, used to get the number of bytes written
  165. // to the stream.
  166. internal sealed class DummyStream: Stream {
  167. private long m_size;
  168. public DummyStream() {
  169. }
  170. private void DontDoIt() {
  171. throw new Exception(Res.GetString(Res.Sql_InternalError));
  172. }
  173. public override bool CanRead {
  174. get {
  175. return false;
  176. }
  177. }
  178. public override bool CanWrite {
  179. get {
  180. return true;
  181. }
  182. }
  183. public override bool CanSeek {
  184. get {
  185. return false;
  186. }
  187. }
  188. public override long Position {
  189. get {
  190. return this.m_size;
  191. }
  192. set {
  193. this.m_size = value;
  194. }
  195. }
  196. public override long Length {
  197. get {
  198. return this.m_size;
  199. }
  200. }
  201. public override void SetLength(long value) {
  202. this.m_size = value;
  203. }
  204. public override long Seek(long value, SeekOrigin loc) {
  205. DontDoIt();
  206. return -1;
  207. }
  208. public override void Flush() {
  209. }
  210. public override int Read(byte[] buffer, int offset, int count) {
  211. DontDoIt();
  212. return -1;
  213. }
  214. public override void Write(byte[] buffer, int offset, int count) {
  215. this.m_size += count;
  216. }
  217. }
  218. }