How to check if an object is serializable in C #

I am looking for an easy way to check if an object in C # is serializable.

As we know, you create an object serializable by implementing the ISerializable interface or by placing [Serializable] at the top of the class.

What I'm looking for is a quick way to test this without thinking about the class to get its attributes. The interface would be fast using the is operator.

Using @Flard's suggestion, this is the code I came up with, screaming is the best way.

private static bool IsSerializable(T obj) { return ((obj is ISerializable) || (Attribute.IsDefined(typeof (T), typeof (SerializableAttribute)))); } 

Or even better, just get the type of the object, and then use the IsSerializable property for the type:

 typeof(T).IsSerializable 

Remember that this only looks like the class we are facing if the class contains other classes that you probably want to test, or try and serialize, and wait for errors, as @pb pointed out.

+84
c # serialization
Sep 17 '08 at 10:08
source share
9 answers

You have a great property in the Type class called IsSerializable .

+97
Sep 17 '08 at 10:20
source share

You will need to check all types in the graph of objects that are serialized for the serializable attribute. The easiest way is to try to serialize the object and catch the exception. (But this is not the purest solution). Type.IsSerializable and serializalbe attribute validation do not count graph.

Example

 [Serializable] public class A { public BB = new B(); } public class B { public string a = "b"; } [Serializable] public class C { public DD = new D(); } [Serializable] public class D { public string d = "D"; } class Program { static void Main(string[] args) { var a = typeof(A); var aa = new A(); Console.WriteLine("A: {0}", a.IsSerializable); // true (WRONG!) var c = typeof(C); Console.WriteLine("C: {0}", c.IsSerializable); //true var form = new BinaryFormatter(); // throws form.Serialize(new MemoryStream(), aa); } } 
+39
Sep 17 '08 at 10:13
source share

This is an old question that might need to be updated for .NET 3.5+. Type.IsSerializable can actually return false if the class uses the DataContract attribute. Here is a snippet that I use if it stinks let me know :)

 public static bool IsSerializable(this object obj) { Type t = obj.GetType(); return Attribute.IsDefined(t, typeof(DataContractAttribute)) || t.IsSerializable || (obj is IXmlSerializable) } 
+16
Oct 27 2018-10-28
source share

Use Type.IsSerializable as others have pointed out.

You should probably not try to mirror and check if all the members in the object graph are serializable.

A member can be declared as a serializable type, but should actually be created as a derived type that is not serializable, as in the following far-fetched example:

 [Serializable] public class MyClass { public Exception TheException; // serializable } public class MyNonSerializableException : Exception { ... } ... MyClass myClass = new MyClass(); myClass.TheException = new MyNonSerializableException(); // myClass now has a non-serializable member 

Therefore, even if you determine that a specific instance of your type is serializable, you cannot even be sure that this will be true for all instances.

+8
Sep 17 '08 at 11:46
source share
 Attribute.IsDefined(typeof (YourClass), typeof (SerializableAttribute)); 

Perhaps includes reflection under water, but the easiest way?

+6
Sep 17 '08 at 10:12
source share

Here is option 3.5, which makes it available to all classes using the extension method.

 public static bool IsSerializable(this object obj) { if (obj is ISerializable) return true; return Attribute.IsDefined(obj.GetType(), typeof(SerializableAttribute)); } 
+5
Sep 17 '08 at 10:29
source share

I took the answer to this question and the answer here and modified it so that you get a list of types that are not serializable. This way you can easily find out which ones to mark.

  private static void NonSerializableTypesOfParentType(Type type, List<string> nonSerializableTypes) { // base case if (type.IsValueType || type == typeof(string)) return; if (!IsSerializable(type)) nonSerializableTypes.Add(type.Name); foreach (var propertyInfo in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { if (propertyInfo.PropertyType.IsGenericType) { foreach (var genericArgument in propertyInfo.PropertyType.GetGenericArguments()) { if (genericArgument == type) continue; // base case for circularly referenced properties NonSerializableTypesOfParentType(genericArgument, nonSerializableTypes); } } else if (propertyInfo.GetType() != type) // base case for circularly referenced properties NonSerializableTypesOfParentType(propertyInfo.PropertyType, nonSerializableTypes); } } private static bool IsSerializable(Type type) { return (Attribute.IsDefined(type, typeof(SerializableAttribute))); //return ((type is ISerializable) || (Attribute.IsDefined(type, typeof(SerializableAttribute)))); } 

And then you call it ...

  List<string> nonSerializableTypes = new List<string>(); NonSerializableTypesOfParentType(aType, nonSerializableTypes); 

When it is launched, the nonSerializableTypes list will have a list. Perhaps this is a better way to do this than passing an empty list to a recursive method. Someone will correct me, if so.

+1
Oct 24 '12 at 17:25
source share

An exception object may be serializable, but using another exception that is not. This is what I just had with WCF System.ServiceModel.FaultException: FaultException is serializable, but ExceptionDetail is not!

Therefore, I use the following:

 // Check if the exception is serializable and also the specific ones if generic var exceptionType = ex.GetType(); var allSerializable = exceptionType.IsSerializable; if (exceptionType.IsGenericType) { Type[] typeArguments = exceptionType.GetGenericArguments(); allSerializable = typeArguments.Aggregate(allSerializable, (current, tParam) => current & tParam.IsSerializable); } if (!allSerializable) { // Create a new Exception for not serializable exceptions! ex = new Exception(ex.Message); } 
0
May 6 '11 at 14:43
source share

My solution in VB.NET:

For objects:

 ''' <summary> ''' Determines whether an object can be serialized. ''' </summary> ''' <param name="Object">The object.</param> ''' <returns><c>true</c> if object can be serialized; otherwise, <c>false</c>.</returns> Private Function IsObjectSerializable(ByVal [Object] As Object, Optional ByVal SerializationFormat As SerializationFormat = SerializationFormat.Xml) As Boolean Dim Serializer As Object Using fs As New IO.MemoryStream Select Case SerializationFormat Case Data.SerializationFormat.Binary Serializer = New Runtime.Serialization.Formatters.Binary.BinaryFormatter() Case Data.SerializationFormat.Xml Serializer = New Xml.Serialization.XmlSerializer([Object].GetType) Case Else Throw New ArgumentException("Invalid SerializationFormat", SerializationFormat) End Select Try Serializer.Serialize(fs, [Object]) Return True Catch ex As InvalidOperationException Return False End Try End Using ' fs As New MemoryStream End Function 

For types:

 ''' <summary> ''' Determines whether a Type can be serialized. ''' </summary> ''' <typeparam name="T"></typeparam> ''' <returns><c>true</c> if Type can be serialized; otherwise, <c>false</c>.</returns> Private Function IsTypeSerializable(Of T)() As Boolean Return Attribute.IsDefined(GetType(T), GetType(SerializableAttribute)) End Function ''' <summary> ''' Determines whether a Type can be serialized. ''' </summary> ''' <typeparam name="T"></typeparam> ''' <param name="Type">The Type.</param> ''' <returns><c>true</c> if Type can be serialized; otherwise, <c>false</c>.</returns> Private Function IsTypeSerializable(Of T)(ByVal Type As T) As Boolean Return Attribute.IsDefined(GetType(T), GetType(SerializableAttribute)) End Function 
0
Aug 02 '14 at 15:24
source share



All Articles