Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 76accdf

Browse files
committed
Merge pull request #13845 from ViktorHofer/DBNull-Serialization
Make DBNull serializable
1 parent 1b28a11 commit 76accdf

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

src/mscorlib/Resources/Strings.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,7 @@
12171217
<value>Cannot use type '{0}'. Only value types without pointers or references are supported.</value>
12181218
</data>
12191219
<data name="Argument_InvalidUnity" xml:space="preserve">
1220-
<value>Invalid Unity type.</value>
1220+
<value>Type '{0}' is not deserializable.</value>
12211221
</data>
12221222
<data name="Argument_InvalidValue" xml:space="preserve">
12231223
<value>Value was invalid.</value>

src/mscorlib/shared/System.Private.CoreLib.Shared.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@
415415
<Compile Include="$(MSBuildThisFileDirectory)System\UnauthorizedAccessException.cs"/>
416416
<Compile Include="$(MSBuildThisFileDirectory)System\UnhandledExceptionEventArgs.cs"/>
417417
<Compile Include="$(MSBuildThisFileDirectory)System\UnhandledExceptionEventHandler.cs"/>
418+
<Compile Include="$(MSBuildThisFileDirectory)System\UnitySerializationHolder.cs"/>
418419
<Compile Include="$(MSBuildThisFileDirectory)System\ValueTuple.cs"/>
419420
<Compile Include="$(MSBuildThisFileDirectory)System\Version.cs"/>
420421
<Compile Include="$(MSBuildThisFileDirectory)System\Void.cs"/>

src/mscorlib/shared/System/DBNull.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,23 @@
66

77
namespace System
88
{
9+
[Serializable]
910
public sealed class DBNull : ISerializable, IConvertible
1011
{
1112
private DBNull()
1213
{
1314
}
14-
15+
16+
private DBNull(SerializationInfo info, StreamingContext context)
17+
{
18+
throw new NotSupportedException(SR.NotSupported_DBNullSerial);
19+
}
20+
1521
public static readonly DBNull Value = new DBNull();
1622

1723
public void GetObjectData(SerializationInfo info, StreamingContext context)
1824
{
19-
throw new PlatformNotSupportedException();
25+
UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.NullUnity);
2026
}
2127

2228
public override string ToString()
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Runtime.Serialization;
6+
7+
namespace System
8+
{
9+
/// <summary>
10+
/// Holds Null class for which we guarantee that there is only ever one instance of.
11+
/// This only exists for compatibility with .NET Framework.
12+
/// </summary>
13+
[Serializable]
14+
#if CORECLR
15+
internal
16+
#else
17+
public // On CoreRT this must be public.
18+
#endif
19+
sealed class UnitySerializationHolder : ISerializable, IObjectReference
20+
{
21+
internal const int NullUnity = 0x0002;
22+
private readonly int _unityType;
23+
private readonly string _data;
24+
25+
/// <summary>
26+
/// A helper method that returns the SerializationInfo that a class utilizing
27+
/// UnitySerializationHelper should return from a call to GetObjectData. It contains
28+
/// the unityType (defined above) and any optional data (used only for the reflection types).
29+
/// </summary>
30+
internal static void GetUnitySerializationInfo(SerializationInfo info, int unityType)
31+
{
32+
info.SetType(typeof(UnitySerializationHolder));
33+
info.AddValue("Data", null, typeof(string));
34+
info.AddValue("UnityType", unityType);
35+
info.AddValue("AssemblyName", string.Empty);
36+
}
37+
38+
public UnitySerializationHolder(SerializationInfo info, StreamingContext context)
39+
{
40+
if (info == null)
41+
{
42+
throw new ArgumentNullException(nameof(info));
43+
}
44+
45+
// We are ignoring any other serialization input as we are only concerned about DBNull.
46+
// We also store data and use it for erorr logging.
47+
_unityType = info.GetInt32("UnityType");
48+
_data = info.GetString("Data");
49+
}
50+
51+
public void GetObjectData(SerializationInfo info, StreamingContext context) =>
52+
throw new NotSupportedException(SR.NotSupported_UnitySerHolder);
53+
54+
public object GetRealObject(StreamingContext context)
55+
{
56+
// We are only support deserializing DBNull and throwing for everything else.
57+
if (_unityType != NullUnity)
58+
{
59+
throw new ArgumentException(SR.Format(SR.Argument_InvalidUnity, _data ?? "UnityType"));
60+
}
61+
62+
// We are always returning the same DBNull instance.
63+
return DBNull.Value;
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)