From de412aa177147d0ed5633cd35ac5a75e998655fb Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Mon, 4 Oct 2021 14:21:11 -0700 Subject: [PATCH 1/7] Move to Shared - SqlSer.cs This is part of Code merge for issue #1261. I have created .common.cs and moved the uncommon code to private methods. --- .../src/Microsoft.Data.SqlClient.csproj | 3 + .../Microsoft/Data/SqlClient/Server/SqlSer.cs | 240 +--------------- .../netfx/src/Microsoft.Data.SqlClient.csproj | 3 + .../Microsoft/Data/SqlClient/Server/sqlser.cs | 238 +--------------- .../Data/SqlClient/Server/SqlSer.Common.cs | 264 ++++++++++++++++++ 5 files changed, 284 insertions(+), 464 deletions(-) create mode 100644 src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.Common.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 7e64b8fd9e..f8dfcf6023 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -274,6 +274,9 @@ Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs + + Microsoft\Data\SqlClient\Server\SqlSer.Common.cs + Microsoft\Data\SqlClient\SignatureVerificationCache.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs index c9f1536f50..e337dd54e4 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs @@ -11,131 +11,10 @@ namespace Microsoft.Data.SqlClient.Server { - internal class SerializationHelperSql9 + internal partial class SerializationHelperSql9 { - // Don't let anyone create an instance of this class. - private SerializationHelperSql9() { } - // Get the m_size of the serialized stream for this type, in bytes. - // This method creates an instance of the type using the public - // no-argument constructor, serializes it, and returns the m_size - // in bytes. - // 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. - [MethodImpl(MethodImplOptions.NoInlining)] - internal static int SizeInBytes(Type t) => SizeInBytes(Activator.CreateInstance(t)); - - // Get the m_size of the serialized stream for this type, in bytes. - internal static int SizeInBytes(object instance) - { - Type t = instance.GetType(); - Format k = GetFormat(t); - DummyStream stream = new DummyStream(); - Serializer ser = GetSerializer(instance.GetType()); - ser.Serialize(stream, instance); - return (int)stream.Length; - } - - internal static void Serialize(Stream s, object instance) - { - GetSerializer(instance.GetType()).Serialize(s, instance); - } - - internal static object Deserialize(Stream s, Type resultType) => GetSerializer(resultType).Deserialize(s); - - private static Format GetFormat(Type t) => GetUdtAttribute(t).Format; - - // Cache the relationship between a type and its serializer. - // This is expensive to compute since it involves traversing the - // custom attributes of the type using reflection. - // - // Use a per-thread cache, so that there are no synchronization - // issues when accessing cache entries from multiple threads. - [ThreadStatic] - private static Hashtable s_types2Serializers; - - private static Serializer GetSerializer(Type t) - { - if (s_types2Serializers == null) - s_types2Serializers = new Hashtable(); - - Serializer s = (Serializer)s_types2Serializers[t]; - if (s == null) - { - s = GetNewSerializer(t); - s_types2Serializers[t] = s; - } - return s; - } - - internal static int GetUdtMaxLength(Type t) - { - SqlUdtInfo udtInfo = SqlUdtInfo.GetFromType(t); - - if (Format.Native == udtInfo.SerializationFormat) - { - // In the native format, the user does not specify the - // max byte size, it is computed from the type definition - return SizeInBytes(t); - } - else - { - // In all other formats, the user specifies the maximum size in bytes. - return udtInfo.MaxByteSize; - } - } - - private static object[] GetCustomAttributes(Type t) - { - object[] attrs = t.GetCustomAttributes(typeof(SqlUserDefinedTypeAttribute), false); - - // If we don't find a Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute, - // search for a Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute from the - // old System.Data.SqlClient assembly and copy it to our - // Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute for reference. - if (attrs == null || attrs.Length == 0) - { - object[] attr = t.GetCustomAttributes(false); - attrs = new object[0]; - if (attr != null && attr.Length > 0) - { - for (int i = 0; i < attr.Length; i++) - { - if (attr[i].GetType().FullName.Equals("Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute")) - { - SqlUserDefinedTypeAttribute newAttr = null; - PropertyInfo[] sourceProps = attr[i].GetType().GetProperties(); - - foreach (PropertyInfo sourceProp in sourceProps) - { - if (sourceProp.Name.Equals("Format")) - { - newAttr = new SqlUserDefinedTypeAttribute((Format)sourceProp.GetValue(attr[i], null)); - break; - } - } - if (newAttr != null) - { - foreach (PropertyInfo targetProp in newAttr.GetType().GetProperties()) - { - if (targetProp.CanRead && targetProp.CanWrite) - { - object copyValue = attr[i].GetType().GetProperty(targetProp.Name).GetValue(attr[i]); - targetProp.SetValue(newAttr, copyValue); - } - } - } - - attrs = new object[1] { newAttr }; - break; - } - } - } - } - - return attrs; - } - - internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) + private static SqlUserDefinedTypeAttribute GetUdtAttributeFrameworkSpecific(Type t) { SqlUserDefinedTypeAttribute udtAttr = null; object[] attr = GetCustomAttributes(t); @@ -151,72 +30,19 @@ internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) return udtAttr; } - // Create a new serializer for the given type. - private static Serializer GetNewSerializer(Type t) - { - SqlUserDefinedTypeAttribute udtAttr = GetUdtAttribute(t); - Format k = GetFormat(t); - - switch (k) - { - case Format.Native: - return new NormalizedSerializer(t); - case Format.UserDefined: - return new BinarySerializeSerializer(t); - case Format.Unknown: // should never happen, but fall through - default: - throw ADP.InvalidUserDefinedTypeSerializationFormat(k); - } - } - } - - // The base serializer class. - internal abstract class Serializer - { - protected Type _type; - - public abstract object Deserialize(Stream s); - public abstract void Serialize(Stream s, object o); - - protected Serializer(Type t) => _type = t; - } - - internal sealed class NormalizedSerializer : Serializer - { - private BinaryOrderedUdtNormalizer _normalizer; - private bool _isFixedSize; - private int _maxSize; - - internal NormalizedSerializer(Type t) : base(t) - { - SqlUserDefinedTypeAttribute udtAttr = SerializationHelperSql9.GetUdtAttribute(t); - _normalizer = new BinaryOrderedUdtNormalizer(t, true); - _isFixedSize = udtAttr.IsFixedLength; - _maxSize = _normalizer.Size; - } - - public override void Serialize(Stream s, object o) => _normalizer.NormalizeTopObject(o, s); - - public override object Deserialize(Stream s) => _normalizer.DeNormalizeTopObject(_type, s); + } - internal sealed class BinarySerializeSerializer : Serializer + internal sealed partial class BinarySerializeSerializer : Serializer { - internal BinarySerializeSerializer(Type t) : base(t) - { - } - - public override void Serialize(Stream s, object o) + private void SerializeFrameworkSpecific(Stream s, object o) { BinaryWriter w = new BinaryWriter(s); ((IBinarySerialize)o).Write(w); } - // Prevent inlining so that reflection calls are not moved - // to a caller that may be in a different assembly that may - // have a different grant set. - [MethodImpl(MethodImplOptions.NoInlining)] - public override object Deserialize(Stream s) + + private object DeserializeFrameworkSpecific(Stream s) { object instance = Activator.CreateInstance(_type); BinaryReader r = new BinaryReader(s); @@ -225,56 +51,4 @@ public override object Deserialize(Stream s) } } - // A dummy stream class, used to get the number of bytes written - // to the stream. - internal sealed class DummyStream : Stream - { - private long _size; - - public DummyStream() - { - } - - private void DontDoIt() - { - throw new Exception(StringsHelper.GetString(Strings.Sql_InternalError)); - } - - public override bool CanRead => false; - - public override bool CanWrite => true; - - public override bool CanSeek => false; - - public override long Position - { - get => _size; - set => _size = value; - } - - public override long Length => _size; - - public override void SetLength(long value) => _size = value; - - public override long Seek(long value, SeekOrigin loc) - { - DontDoIt(); - return -1; - } - - public override void Flush() - { - } - - public override int Read(byte[] buffer, int offset, int count) - { - DontDoIt(); - return -1; - } - - public override void Write(byte[] buffer, int offset, int count) - { - _size += count; - } - } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index ae61c39607..ae20813bd1 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -216,6 +216,9 @@ Microsoft\Data\SqlClient\Server\SmiMetaData.cs + + Microsoft\Data\SqlClient\Server\SqlSer.Common.cs + Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs index 2967aaaa55..9d09080532 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs @@ -11,131 +11,11 @@ namespace Microsoft.Data.SqlClient.Server { - internal class SerializationHelperSql9 - { - // Don't let anyone create an instance of this class. - private SerializationHelperSql9() { } - - // Get the m_size of the serialized stream for this type, in bytes. - // This method creates an instance of the type using the public - // no-argument constructor, serializes it, and returns the m_size - // in bytes. - // 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. - [MethodImpl(MethodImplOptions.NoInlining)] - internal static int SizeInBytes(Type t) => SizeInBytes(Activator.CreateInstance(t)); - - // Get the m_size of the serialized stream for this type, in bytes. - internal static int SizeInBytes(object instance) - { - Type t = instance.GetType(); - Format k = GetFormat(t); - DummyStream stream = new DummyStream(); - Serializer ser = GetSerializer(instance.GetType()); - ser.Serialize(stream, instance); - return (int)stream.Length; - } - - internal static void Serialize(Stream s, object instance) - { - GetSerializer(instance.GetType()).Serialize(s, instance); - } - - internal static object Deserialize(Stream s, Type resultType) => GetSerializer(resultType).Deserialize(s); - - private static Format GetFormat(Type t) => GetUdtAttribute(t).Format; - - // Cache the relationship between a type and its serializer. - // This is expensive to compute since it involves traversing the - // custom attributes of the type using reflection. - // - // Use a per-thread cache, so that there are no synchronization - // issues when accessing cache entries from multiple threads. - [ThreadStatic] - private static Hashtable s_types2Serializers; - - private static Serializer GetSerializer(Type t) - { - if (s_types2Serializers == null) - s_types2Serializers = new Hashtable(); - - Serializer s = (Serializer)s_types2Serializers[t]; - if (s == null) - { - s = GetNewSerializer(t); - s_types2Serializers[t] = s; - } - return s; - } - - internal static int GetUdtMaxLength(Type t) - { - SqlUdtInfo udtInfo = SqlUdtInfo.GetFromType(t); - - if (Format.Native == udtInfo.SerializationFormat) - { - // In the native format, the user does not specify the - // max byte size, it is computed from the type definition - return SerializationHelperSql9.SizeInBytes(t); - } - else - { - // In all other formats, the user specifies the maximum size in bytes. - return udtInfo.MaxByteSize; - } - } - private static object[] GetCustomAttributes(Type t) - { - object[] attrs = t.GetCustomAttributes(typeof(SqlUserDefinedTypeAttribute), false); - - // If we don't find a Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute, - // search for a Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute from the - // old System.Data.SqlClient assembly and copy it to our - // Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute for reference. - if (attrs == null || attrs.Length == 0) - { - object[] attr = t.GetCustomAttributes(false); - attrs = new object[0]; - if (attr != null && attr.Length > 0) - { - for (int i = 0; i < attr.Length; i++) - { - if (attr[i].GetType().FullName.Equals("Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute")) - { - SqlUserDefinedTypeAttribute newAttr = null; - PropertyInfo[] sourceProps = attr[i].GetType().GetProperties(); - - foreach (PropertyInfo sourceProp in sourceProps) - { - if (sourceProp.Name.Equals("Format")) - { - newAttr = new SqlUserDefinedTypeAttribute((Format)sourceProp.GetValue(attr[i], null)); - break; - } - } - if (newAttr != null) - { - foreach (PropertyInfo targetProp in newAttr.GetType().GetProperties()) - { - if (targetProp.CanRead && targetProp.CanWrite) - { - object copyValue = attr[i].GetType().GetProperty(targetProp.Name).GetValue(attr[i]); - targetProp.SetValue(newAttr, copyValue); - } - } - } - - attrs = new object[1] { newAttr }; - break; - } - } - } - } - - return attrs; - } + internal partial class SerializationHelperSql9 + { - internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) + private static SqlUserDefinedTypeAttribute GetUdtAttributeFrameworkSpecific(Type t) { SqlUserDefinedTypeAttribute udtAttr = null; object[] attr = GetCustomAttributes(t); @@ -153,64 +33,11 @@ internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) } return udtAttr; } - - // Create a new serializer for the given type. - private static Serializer GetNewSerializer(Type t) - { - SqlUserDefinedTypeAttribute udtAttr = GetUdtAttribute(t); - - switch (udtAttr.Format) - { - case Format.Native: - return new NormalizedSerializer(t); - case Format.UserDefined: - return new BinarySerializeSerializer(t); - case Format.Unknown: // should never happen, but fall through - default: - throw ADP.InvalidUserDefinedTypeSerializationFormat(udtAttr.Format); - } - } - } - - // The base serializer class. - internal abstract class Serializer - { - public abstract object Deserialize(Stream s); - public abstract void Serialize(Stream s, object o); - protected Type _type; - - protected Serializer(Type t) - { - _type = t; - } } - internal sealed class NormalizedSerializer : Serializer + internal sealed partial class BinarySerializeSerializer : Serializer { - private BinaryOrderedUdtNormalizer _normalizer; - private bool _isFixedSize; - private int _maxSize; - - internal NormalizedSerializer(Type t) : base(t) - { - SqlUserDefinedTypeAttribute udtAttr = SerializationHelperSql9.GetUdtAttribute(t); - _normalizer = new BinaryOrderedUdtNormalizer(t, true); - _isFixedSize = udtAttr.IsFixedLength; - _maxSize = _normalizer.Size; - } - - public override void Serialize(Stream s, object o) => _normalizer.NormalizeTopObject(o, s); - - public override object Deserialize(Stream s) => _normalizer.DeNormalizeTopObject(_type, s); - } - - internal sealed class BinarySerializeSerializer : Serializer - { - internal BinarySerializeSerializer(Type t) : base(t) - { - } - - public override void Serialize(Stream s, object o) + private void SerializeFrameworkSpecific(Stream s, object o) { BinaryWriter w = new BinaryWriter(s); if (o is Microsoft.SqlServer.Server.IBinarySerialize) @@ -223,11 +50,7 @@ public override void Serialize(Stream s, object o) } } - // Prevent inlining so that reflection calls are not moved - // to a caller that may be in a different assembly that may - // have a different grant set. - [MethodImpl(MethodImplOptions.NoInlining)] - public override object Deserialize(Stream s) + private object DeserializeFrameworkSpecific(Stream s) { object instance = Activator.CreateInstance(_type); BinaryReader r = new BinaryReader(s); @@ -241,55 +64,8 @@ public override object Deserialize(Stream s) } return instance; } - } - - // A dummy stream class, used to get the number of bytes written - // to the stream. - internal sealed class DummyStream : Stream - { - private long _size; - - public DummyStream() - { - } - - private void DontDoIt() - { - throw new Exception(StringsHelper.GetString(Strings.Sql_InternalError)); - } - - public override bool CanRead => false; - - public override bool CanWrite => true; - - public override bool CanSeek => false; - - public override long Position - { - get => _size; - set =>_size = value; - } - - public override long Length => _size; - public override void SetLength(long value) => _size = value; - - public override long Seek(long value, SeekOrigin loc) - { - DontDoIt(); - return -1; - } - - public override void Flush() - { - } + } - public override int Read(byte[] buffer, int offset, int count) - { - DontDoIt(); - return -1; - } - public override void Write(byte[] buffer, int offset, int count) => _size += count; - } } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.Common.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.Common.cs new file mode 100644 index 0000000000..80b28ddbd6 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.Common.cs @@ -0,0 +1,264 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.Data.Common; + +namespace Microsoft.Data.SqlClient.Server +{ + internal partial class SerializationHelperSql9 + { + // Don't let anyone create an instance of this class. + private SerializationHelperSql9() { } + + // Get the m_size of the serialized stream for this type, in bytes. + // This method creates an instance of the type using the public + // no-argument constructor, serializes it, and returns the + // in bytes. + // 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. + [MethodImpl(MethodImplOptions.NoInlining)] + internal static int SizeInBytes(Type t) => SizeInBytes(Activator.CreateInstance(t)); + + // Get the m_size of the serialized stream for this type, in bytes. + internal static int SizeInBytes(object instance) + { + Type t = instance.GetType(); + Format k = GetFormat(t); + DummyStream stream = new DummyStream(); + Serializer ser = GetSerializer(instance.GetType()); + ser.Serialize(stream, instance); + return (int)stream.Length; + } + + internal static void Serialize(Stream s, object instance) + { + GetSerializer(instance.GetType()).Serialize(s, instance); + } + + internal static object Deserialize(Stream s, Type resultType) => GetSerializer(resultType).Deserialize(s); + + private static Format GetFormat(Type t) => GetUdtAttribute(t).Format; + + // Cache the relationship between a type and its serializer. + // This is expensive to compute since it involves traversing the + // custom attributes of the type using reflection. + // + // Use a per-thread cache, so that there are no synchronization + // issues when accessing cache entries from multiple threads. + [ThreadStatic] + private static Hashtable s_types2Serializers; + + private static Serializer GetSerializer(Type t) + { + if (s_types2Serializers == null) + s_types2Serializers = new Hashtable(); + + Serializer s = (Serializer)s_types2Serializers[t]; + if (s == null) + { + s = GetNewSerializer(t); + s_types2Serializers[t] = s; + } + return s; + } + + internal static int GetUdtMaxLength(Type t) + { + SqlUdtInfo udtInfo = SqlUdtInfo.GetFromType(t); + + if (Format.Native == udtInfo.SerializationFormat) + { + // In the native format, the user does not specify the + // max byte size, it is computed from the type definition + return SizeInBytes(t); + } + else + { + // In all other formats, the user specifies the maximum size in bytes. + return udtInfo.MaxByteSize; + } + } + + private static object[] GetCustomAttributes(Type t) + { + object[] attrs = t.GetCustomAttributes(typeof(SqlUserDefinedTypeAttribute), false); + + // If we don't find a Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute, + // search for a Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute from the + // old System.Data.SqlClient assembly and copy it to our + // Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute for reference. + if (attrs == null || attrs.Length == 0) + { + object[] attr = t.GetCustomAttributes(false); + attrs = new object[0]; + if (attr != null && attr.Length > 0) + { + for (int i = 0; i < attr.Length; i++) + { + if (attr[i].GetType().FullName.Equals("Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute")) + { + SqlUserDefinedTypeAttribute newAttr = null; + PropertyInfo[] sourceProps = attr[i].GetType().GetProperties(); + + foreach (PropertyInfo sourceProp in sourceProps) + { + if (sourceProp.Name.Equals("Format")) + { + newAttr = new SqlUserDefinedTypeAttribute((Format)sourceProp.GetValue(attr[i], null)); + break; + } + } + if (newAttr != null) + { + foreach (PropertyInfo targetProp in newAttr.GetType().GetProperties()) + { + if (targetProp.CanRead && targetProp.CanWrite) + { + object copyValue = attr[i].GetType().GetProperty(targetProp.Name).GetValue(attr[i]); + targetProp.SetValue(newAttr, copyValue); + } + } + } + + attrs = new object[1] { newAttr }; + break; + } + } + } + } + + return attrs; + } + + internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) + { + return GetUdtAttributeFrameworkSpecific(t); + } + + // Create a new serializer for the given type. + private static Serializer GetNewSerializer(Type t) + { + SqlUserDefinedTypeAttribute udtAttr = GetUdtAttribute(t); + + switch (udtAttr.Format) + { + case Format.Native: + return new NormalizedSerializer(t); + case Format.UserDefined: + return new BinarySerializeSerializer(t); + case Format.Unknown: // should never happen, but fall through + default: + throw ADP.InvalidUserDefinedTypeSerializationFormat(udtAttr.Format); + } + } + } + + // The base serializer class. + internal abstract class Serializer + { + protected Type _type; + + public abstract object Deserialize(Stream s); + public abstract void Serialize(Stream s, object o); + + protected Serializer(Type t) => _type = t; + } + + internal sealed class NormalizedSerializer : Serializer + { + private BinaryOrderedUdtNormalizer _normalizer; + private bool _isFixedSize; + private int _maxSize; + + internal NormalizedSerializer(Type t) : base(t) + { + SqlUserDefinedTypeAttribute udtAttr = SerializationHelperSql9.GetUdtAttribute(t); + _normalizer = new BinaryOrderedUdtNormalizer(t, true); + _isFixedSize = udtAttr.IsFixedLength; + _maxSize = _normalizer.Size; + } + + public override void Serialize(Stream s, object o) => _normalizer.NormalizeTopObject(o, s); + + public override object Deserialize(Stream s) => _normalizer.DeNormalizeTopObject(_type, s); + } + + internal sealed partial class BinarySerializeSerializer : Serializer + { + internal BinarySerializeSerializer(Type t) : base(t) + { + } + + public override void Serialize(Stream s, object o) + { + SerializeFrameworkSpecific(s, o); + } + + // Prevent inlining so that reflection calls are not moved + // to a caller that may be in a different assembly that may + // have a different grant set. + [MethodImpl(MethodImplOptions.NoInlining)] + public override object Deserialize(Stream s) + { + return DeserializeFrameworkSpecific(s); + } + } + + // A dummy stream class, used to get the number of bytes written + // to the stream. + internal sealed class DummyStream : Stream + { + private long _size; + + public DummyStream() + { + } + + private void DontDoIt() + { + throw new Exception(StringsHelper.GetString(Strings.Sql_InternalError)); + } + + public override bool CanRead => false; + + public override bool CanWrite => true; + + public override bool CanSeek => false; + + public override long Position + { + get => _size; + set => _size = value; + } + + public override long Length => _size; + + public override void SetLength(long value) => _size = value; + + public override long Seek(long value, SeekOrigin loc) + { + DontDoIt(); + return -1; + } + + public override void Flush() + { + } + + public override int Read(byte[] buffer, int offset, int count) + { + DontDoIt(); + return -1; + } + + public override void Write(byte[] buffer, int offset, int count) + { + _size += count; + } + } +} From 77c2ae582fcb3e4465676715497e9654daaafb04 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Thu, 7 Oct 2021 12:31:41 -0700 Subject: [PATCH 2/7] addressing reviewer's comment Removed Netfx and Netcore files for SqlSer and added Netfx if endifs in common file --- .../src/Microsoft.Data.SqlClient.csproj | 5 +- .../Microsoft/Data/SqlClient/Server/SqlSer.cs | 54 -------------- .../netfx/src/Microsoft.Data.SqlClient.csproj | 7 +- .../Microsoft/Data/SqlClient/Server/sqlser.cs | 71 ------------------- .../Server/{SqlSer.Common.cs => SqlSer.cs} | 46 ++++++++++-- 5 files changed, 44 insertions(+), 139 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs rename src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/{SqlSer.Common.cs => SqlSer.cs} (86%) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 9e15139c86..c36752d007 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -295,8 +295,8 @@ Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs - - Microsoft\Data\SqlClient\Server\SqlSer.Common.cs + + Microsoft\Data\SqlClient\Server\SqlSer.cs Microsoft\Data\SqlClient\SignatureVerificationCache.cs @@ -494,7 +494,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs deleted file mode 100644 index e337dd54e4..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlSer.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections; -using System.IO; -using System.Reflection; -using System.Runtime.CompilerServices; -using Microsoft.Data.Common; - -namespace Microsoft.Data.SqlClient.Server -{ - internal partial class SerializationHelperSql9 - { - - private static SqlUserDefinedTypeAttribute GetUdtAttributeFrameworkSpecific(Type t) - { - SqlUserDefinedTypeAttribute udtAttr = null; - object[] attr = GetCustomAttributes(t); - - if (attr != null && attr.Length == 1) - { - udtAttr = (SqlUserDefinedTypeAttribute)attr[0]; - } - else - { - throw InvalidUdtException.Create(t, Strings.SqlUdtReason_NoUdtAttribute); - } - return udtAttr; - } - - - } - - internal sealed partial class BinarySerializeSerializer : Serializer - { - private void SerializeFrameworkSpecific(Stream s, object o) - { - BinaryWriter w = new BinaryWriter(s); - ((IBinarySerialize)o).Write(w); - } - - - private object DeserializeFrameworkSpecific(Stream s) - { - object instance = Activator.CreateInstance(_type); - BinaryReader r = new BinaryReader(s); - ((IBinarySerialize)instance).Read(r); - return instance; - } - } - -} diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 3a0a94bdd7..2cc8839486 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -222,8 +222,8 @@ Microsoft\Data\SqlClient\Server\SmiMetaData.cs - - Microsoft\Data\SqlClient\Server\SqlSer.Common.cs + + Microsoft\Data\SqlClient\Server\SqlSer.cs Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs @@ -564,7 +564,6 @@ - @@ -643,4 +642,4 @@ - \ No newline at end of file + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs deleted file mode 100644 index 9d09080532..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/sqlser.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections; -using System.IO; -using System.Reflection; -using System.Runtime.CompilerServices; -using Microsoft.Data.Common; - -namespace Microsoft.Data.SqlClient.Server -{ - - internal partial class SerializationHelperSql9 - { - - private static SqlUserDefinedTypeAttribute GetUdtAttributeFrameworkSpecific(Type t) - { - SqlUserDefinedTypeAttribute udtAttr = null; - object[] attr = GetCustomAttributes(t); - - if (attr != null && attr.Length == 1) - { - udtAttr = (SqlUserDefinedTypeAttribute)attr[0]; - } - else - { - Type InvalidUdtExceptionType = typeof(InvalidUdtException); - var arguments = new Type[] { typeof(Type), typeof(String) }; - MethodInfo Create = InvalidUdtExceptionType.GetMethod("Create", arguments); - Create.Invoke(null, new object[] { t, Strings.SqlUdtReason_NoUdtAttribute }); - } - return udtAttr; - } - } - - internal sealed partial class BinarySerializeSerializer : Serializer - { - private void SerializeFrameworkSpecific(Stream s, object o) - { - BinaryWriter w = new BinaryWriter(s); - if (o is Microsoft.SqlServer.Server.IBinarySerialize) - { - ((SqlServer.Server.IBinarySerialize)o).Write(w); - } - else - { - ((IBinarySerialize)o).Write(w); - } - } - - private object DeserializeFrameworkSpecific(Stream s) - { - object instance = Activator.CreateInstance(_type); - BinaryReader r = new BinaryReader(s); - if (instance is Microsoft.SqlServer.Server.IBinarySerialize) - { - ((SqlServer.Server.IBinarySerialize)instance).Read(r); - } - else - { - ((IBinarySerialize)instance).Read(r); - } - return instance; - } - - } - - -} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.Common.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs similarity index 86% rename from src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.Common.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs index 80b28ddbd6..7d166d0f8c 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.Common.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs @@ -137,7 +137,17 @@ private static object[] GetCustomAttributes(Type t) internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) { - return GetUdtAttributeFrameworkSpecific(t); + SqlUserDefinedTypeAttribute udtAttr = null; + object[] attr = GetCustomAttributes(t); + if (attr != null && attr.Length == 1) + { + udtAttr = (SqlUserDefinedTypeAttribute)attr[0]; + } + else + { + throw InvalidUdtException.Create(t, Strings.SqlUdtReason_NoUdtAttribute); + } + return udtAttr; } // Create a new serializer for the given type. @@ -196,16 +206,38 @@ internal BinarySerializeSerializer(Type t) : base(t) public override void Serialize(Stream s, object o) { - SerializeFrameworkSpecific(s, o); + BinaryWriter w = new BinaryWriter(s); + +#if NETFRAMEWORK + if (o is Microsoft.SqlServer.Server.IBinarySerialize) + { + ((SqlServer.Server.IBinarySerialize)o).Write(w); + return; + } +#endif + ((IBinarySerialize)o).Write(w); + } - // Prevent inlining so that reflection calls are not moved - // to a caller that may be in a different assembly that may - // have a different grant set. - [MethodImpl(MethodImplOptions.NoInlining)] + // Prevent inlining so that reflection calls are not moved + // to a caller that may be in a different assembly that may + // have a different grant set. + [MethodImpl(MethodImplOptions.NoInlining)] public override object Deserialize(Stream s) { - return DeserializeFrameworkSpecific(s); + object instance = Activator.CreateInstance(_type); + BinaryReader r = new BinaryReader(s); + +#if NETFRAMEWORK + if (instance is Microsoft.SqlServer.Server.IBinarySerialize) + { + ((SqlServer.Server.IBinarySerialize)instance).Read(r); + return instance; + } +#endif + ((IBinarySerialize)instance).Read(r); + return instance; + } } From a929c73f4eb525ad9eebfb1af65935a436d2c046 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Thu, 7 Oct 2021 14:11:37 -0700 Subject: [PATCH 3/7] Updating common class not to be partial Just updating class not use partial anymore, indentation, comment correction --- .../src/Microsoft/Data/SqlClient/Server/SqlSer.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs index 7d166d0f8c..ee99c4e5a0 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs @@ -11,14 +11,14 @@ namespace Microsoft.Data.SqlClient.Server { - internal partial class SerializationHelperSql9 + internal class SerializationHelperSql9 { // Don't let anyone create an instance of this class. private SerializationHelperSql9() { } // Get the m_size of the serialized stream for this type, in bytes. // This method creates an instance of the type using the public - // no-argument constructor, serializes it, and returns the + // no-argument constructor, serializes it, and returns the m_size // in bytes. // 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. [MethodImpl(MethodImplOptions.NoInlining)] @@ -198,7 +198,7 @@ internal NormalizedSerializer(Type t) : base(t) public override object Deserialize(Stream s) => _normalizer.DeNormalizeTopObject(_type, s); } - internal sealed partial class BinarySerializeSerializer : Serializer + internal sealed class BinarySerializeSerializer : Serializer { internal BinarySerializeSerializer(Type t) : base(t) { @@ -219,10 +219,10 @@ public override void Serialize(Stream s, object o) } - // Prevent inlining so that reflection calls are not moved - // to a caller that may be in a different assembly that may - // have a different grant set. - [MethodImpl(MethodImplOptions.NoInlining)] + // Prevent inlining so that reflection calls are not moved + // to a caller that may be in a different assembly that may + // have a different grant set. + [MethodImpl(MethodImplOptions.NoInlining)] public override object Deserialize(Stream s) { object instance = Activator.CreateInstance(_type); From e6b777c9c5c09a7c9f62fff7453cee31254becbf Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Wed, 22 Dec 2021 16:06:48 -0800 Subject: [PATCH 4/7] addressing review comments addressing review comments --- .../Microsoft/Data/SqlClient/Server/SqlSer.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs index ee99c4e5a0..d3639d4df1 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs @@ -4,6 +4,7 @@ using System; using System.Collections; +using System.Collections.Concurrent; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; @@ -11,7 +12,7 @@ namespace Microsoft.Data.SqlClient.Server { - internal class SerializationHelperSql9 + internal sealed class SerializationHelperSql9 { // Don't let anyone create an instance of this class. private SerializationHelperSql9() { } @@ -50,13 +51,14 @@ internal static void Serialize(Stream s, object instance) // // Use a per-thread cache, so that there are no synchronization // issues when accessing cache entries from multiple threads. - [ThreadStatic] - private static Hashtable s_types2Serializers; + private static ConcurrentDictionary s_types2Serializers; private static Serializer GetSerializer(Type t) { if (s_types2Serializers == null) - s_types2Serializers = new Hashtable(); + { + s_types2Serializers = new(); + } Serializer s = (Serializer)s_types2Serializers[t]; if (s == null) @@ -209,9 +211,9 @@ public override void Serialize(Stream s, object o) BinaryWriter w = new BinaryWriter(s); #if NETFRAMEWORK - if (o is Microsoft.SqlServer.Server.IBinarySerialize) + if (o is SqlServer.Server.IBinarySerialize bs) { - ((SqlServer.Server.IBinarySerialize)o).Write(w); + (bs).Write(w); return; } #endif @@ -229,9 +231,9 @@ public override object Deserialize(Stream s) BinaryReader r = new BinaryReader(s); #if NETFRAMEWORK - if (instance is Microsoft.SqlServer.Server.IBinarySerialize) + if (instance is SqlServer.Server.IBinarySerialize bs) { - ((SqlServer.Server.IBinarySerialize)instance).Read(r); + bs.Read(r); return instance; } #endif From 027692468ef6bda99268e1f54caa59330962ddb0 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Wed, 22 Dec 2021 16:46:53 -0800 Subject: [PATCH 5/7] VSCode suggestions VSCode suggestions --- .../src/Microsoft/Data/SqlClient/Server/SqlSer.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs index d3639d4df1..cd5961de85 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs @@ -29,7 +29,8 @@ private SerializationHelperSql9() { } internal static int SizeInBytes(object instance) { Type t = instance.GetType(); - Format k = GetFormat(t); + + _ = GetFormat(t); DummyStream stream = new DummyStream(); Serializer ser = GetSerializer(instance.GetType()); ser.Serialize(stream, instance); @@ -139,7 +140,7 @@ private static object[] GetCustomAttributes(Type t) internal static SqlUserDefinedTypeAttribute GetUdtAttribute(Type t) { - SqlUserDefinedTypeAttribute udtAttr = null; + SqlUserDefinedTypeAttribute udtAttr; object[] attr = GetCustomAttributes(t); if (attr != null && attr.Length == 1) { @@ -183,16 +184,12 @@ internal abstract class Serializer internal sealed class NormalizedSerializer : Serializer { - private BinaryOrderedUdtNormalizer _normalizer; - private bool _isFixedSize; - private int _maxSize; - + private readonly BinaryOrderedUdtNormalizer _normalizer; + internal NormalizedSerializer(Type t) : base(t) { - SqlUserDefinedTypeAttribute udtAttr = SerializationHelperSql9.GetUdtAttribute(t); + _ = SerializationHelperSql9.GetUdtAttribute(t); _normalizer = new BinaryOrderedUdtNormalizer(t, true); - _isFixedSize = udtAttr.IsFixedLength; - _maxSize = _normalizer.Size; } public override void Serialize(Stream s, object o) => _normalizer.NormalizeTopObject(o, s); From 500e56c18a573bf33f6e98e1d21b13fe5e447d1f Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Fri, 24 Dec 2021 11:14:57 -0800 Subject: [PATCH 6/7] Added check for key in dictionary and addressed review comments Added check for key in dictionary and addressed review comments --- .../src/Microsoft/Data/SqlClient/Server/SqlSer.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs index cd5961de85..567d99a951 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs @@ -56,13 +56,17 @@ internal static void Serialize(Stream s, object instance) private static Serializer GetSerializer(Type t) { + Serializer s = null; if (s_types2Serializers == null) { - s_types2Serializers = new(); + s_types2Serializers = new ConcurrentDictionary(); } - Serializer s = (Serializer)s_types2Serializers[t]; - if (s == null) + if (s_types2Serializers.ContainsKey(t)) + { + s = s_types2Serializers[t]; + } + else { s = GetNewSerializer(t); s_types2Serializers[t] = s; From bba0883ec31d007a413e7cc75b4d92cfa1ce545a Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Mon, 10 Jan 2022 13:05:15 -0800 Subject: [PATCH 7/7] addressing comments --- .../src/Microsoft/Data/SqlClient/Server/SqlSer.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs index 567d99a951..cf510834b6 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlSer.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections; using System.Collections.Concurrent; using System.IO; using System.Reflection; @@ -56,21 +55,18 @@ internal static void Serialize(Stream s, object instance) private static Serializer GetSerializer(Type t) { - Serializer s = null; if (s_types2Serializers == null) { s_types2Serializers = new ConcurrentDictionary(); } - if (s_types2Serializers.ContainsKey(t)) - { - s = s_types2Serializers[t]; - } - else + Serializer s; + if (!s_types2Serializers.TryGetValue(t, out s)) { s = GetNewSerializer(t); s_types2Serializers[t] = s; } + return s; }