Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to Shared - SqlSer.cs #1313

Merged
merged 14 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs">
<Link>Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\Server\SqlSer.Common.cs">
<Link>Microsoft\Data\SqlClient\Server\SqlSer.Common.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\SignatureVerificationCache.cs">
<Link>Microsoft\Data\SqlClient\SignatureVerificationCache.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@
<Compile Include="..\..\src\Microsoft\Data\SqlClient\Server\SmiMetaData.cs">
<Link>Microsoft\Data\SqlClient\Server\SmiMetaData.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\Server\SqlSer.Common.cs">
<Link>Microsoft\Data\SqlClient\Server\SqlSer.Common.cs</Link>
</Compile>
<Compile Include="..\..\src\Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs">
<Link>Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs</Link>
</Compile>
Expand Down
Loading