Make DBNull serializable
authorViktor Hofer <viktor.hofer@outlook.com>
Thu, 7 Sep 2017 21:57:22 +0000 (23:57 +0200)
committerViktor Hofer <viktor.hofer@outlook.com>
Thu, 7 Sep 2017 22:36:10 +0000 (00:36 +0200)
src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
src/mscorlib/shared/System/DBNull.cs
src/mscorlib/shared/System/UnitySerializationHolder.cs [new file with mode: 0644]

index bd68b542f1e476cb86ef8f99286ec99a0c146085..9811130940152e5a655063a8bb5d9a5ec06b6920 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\UnauthorizedAccessException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\UnhandledExceptionEventArgs.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\UnhandledExceptionEventHandler.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\UnitySerializationHolder.cs"/> 
     <Compile Include="$(MSBuildThisFileDirectory)System\ValueTuple.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Version.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Void.cs" />
index 4f4d64bf66158ad752651292be053b51d5c67531..486eb72f2acc2bde1511261bfdf92d6ea31c68c2 100644 (file)
@@ -6,17 +6,23 @@ using System.Runtime.Serialization;
 
 namespace System
 {
+    [Serializable]
     public sealed class DBNull : ISerializable, IConvertible
     {
         private DBNull()
         {
         }
-        
+
+        private DBNull(SerializationInfo info, StreamingContext context)
+        {
+            throw new NotSupportedException(SR.NotSupported_DBNullSerial);
+        }
+
         public static readonly DBNull Value = new DBNull();
 
         public void GetObjectData(SerializationInfo info, StreamingContext context)
         {
-            throw new PlatformNotSupportedException();
+            UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.NullUnity, null, null);
         }
 
         public override string ToString()
diff --git a/src/mscorlib/shared/System/UnitySerializationHolder.cs b/src/mscorlib/shared/System/UnitySerializationHolder.cs
new file mode 100644 (file)
index 0000000..d2aa882
--- /dev/null
@@ -0,0 +1,58 @@
+// 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.Runtime.Serialization;
+using System.Reflection;
+using System.Diagnostics.Contracts;
+
+namespace System
+{
+    // Holds classes (Empty, Null, Missing) for which we guarantee that there is only ever one instance of.
+#if CORECLR
+    internal
+#else
+    public  // On CoreRT, this must be public because of the Reflection.Core/CoreLib divide and the need to whitelist past the ReflectionBlock.
+#endif
+    class UnitySerializationHolder : ISerializable, IObjectReference
+    {
+        internal const int NullUnity = 0x0002;
+        const string DataName = "Data";
+        const string UnityTypeName = "UnityType";
+        const string AssemblyNameName = "AssemblyName";
+
+        private readonly string _data;
+        private readonly string _assemblyName;
+        private int _unityType;
+
+        public static void GetUnitySerializationInfo(SerializationInfo info, int unityType, string data, Assembly assembly)
+        {
+            // A helper method that returns the SerializationInfo that a class utilizing 
+            // UnitySerializationHelper should return from a call to GetObjectData.  It contains
+            // the unityType (defined above) and any optional data (used only for the reflection
+            // types.)
+
+            info.SetType(typeof(UnitySerializationHolder));
+            info.AddValue(DataName, data, typeof(string));
+            info.AddValue(UnityTypeName, unityType);
+            info.AddValue(AssemblyNameName, assembly?.FullName ?? string.Empty);
+        }
+
+        public UnitySerializationHolder(SerializationInfo info, StreamingContext context)
+        {
+            if (info == null)
+            {
+                throw new ArgumentNullException(nameof(info));
+            }
+
+            _unityType = info.GetInt32(UnityTypeName);
+            _data = info.GetString(DataName);
+            _assemblyName = info.GetString(AssemblyNameName);
+        }
+
+        public virtual void GetObjectData(SerializationInfo info, StreamingContext context) =>
+            throw new NotSupportedException(SR.NotSupported_UnitySerHolder);
+
+        public virtual object GetRealObject(StreamingContext context) => DBNull.Value;
+    }
+}