How to determine if a .NET Standard object is serializable

.NET Standard is a specification that defines the types and members that must be present on specific .NET implementations that conform to that version of the standard. However, .NET Standard does not define whether a type is serializable. The types defined in the .NET Standard Library are not marked with the SerializableAttribute attribute. Instead, specific .NET implementations, such as .NET Framework and .NET Core, are free to determine whether a particular type is serializable.

If you've developed a library that targets .NET Standard, your library can be consumed by any .NET implementation that supports .NET Standard. This means that you cannot know in advance whether a particular type is serializable; you can only determine whether it is serializable at run time.

You can determine whether an object is serializable at run time by retrieving the value of the IsSerializable property of a Type object that represents that object's type. The following example provides one implementation. It defines an IsSerializable(Object) extension method that indicates whether any Object instance can be serialized.

namespace Libraries
{
    using System;

    public static class UtilityLibrary
    {
        public static bool IsSerializable(this object obj)
        {
            if (obj == null)
                return false;

            Type t = obj.GetType();
            return t.IsSerializable;
        }
    }
}
Imports System.Runtime.CompilerServices

Namespace Global.Libraries

    Public Module UtilityLibrary
        <Extension>
        Public Function IsSerializable(obj As Object) As Boolean
            If obj Is Nothing Then Return False

            Dim t As Type = obj.GetType()
            Return t.IsSerializable
        End Function
    End Module
End Namespace

You can then pass any object to the method to determine whether it can be serialized and deserialized on the current .NET implementation, as the following example shows:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Libraries;

namespace test_serialization
{
   class Program
   {
      static void Main()
      {
         var value = ValueTuple.Create("03244562", DateTime.Now, 13452.50m);
         if (value.IsSerializable())
         {
            // Serialize the value tuple.
            var formatter = new BinaryFormatter();
            using (var stream = new FileStream("data.bin", FileMode.Create,
                                        FileAccess.Write, FileShare.None))
            {
               formatter.Serialize(stream, value);
            }
            // Deserialize the value tuple.
            using (var readStream = new FileStream("data.bin", FileMode.Open))
            {
               object restoredValue = formatter.Deserialize(readStream);
               Console.WriteLine($"{restoredValue.GetType().Name}: {restoredValue}");
            }
         }
         else
         {
            Console.WriteLine($"{nameof(value)} is not serializable");
         }
      }
   }
}
// The example displays output like the following:
//    ValueTuple`3: (03244562, 10/18/2017 5:25:22 PM, 13452.50)
Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
Imports Libraries

Module Program
    Sub Main()
        Dim value = ValueTuple.Create("03244562", DateTime.Now, 13452.50d)
        If value.IsSerializable() Then
            Dim formatter As New BinaryFormatter()
            ' Serialize the value tuple.
            Using stream As New FileStream("data.bin", FileMode.Create,
                                           FileAccess.Write, FileShare.None)
                formatter.Serialize(stream, value)
            End Using
            ' Deserialize the value tuple.
            Using readStream As New FileStream("data.bin", FileMode.Open)
                Dim restoredValue = formatter.Deserialize(readStream)
                Console.WriteLine($"{restoredValue.GetType().Name}: {restoredValue}")
            End Using
        Else
            Console.WriteLine($"{nameof(value)} is not serializable")
        End If
    End Sub
End Module
' The example displays output like the following:
'    ValueTuple`3: (03244562, 10/18/2017 5:25:22 PM, 13452.50)

See also