How to check if an object is serializable in C#

后端 未结 9 2058
太阳男子
太阳男子 2020-12-04 17:35

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

As we know you make an object serializable by either implementing the ISerializable

相关标签:
9条回答
  • 2020-12-04 17:42

    I took the answer on this question and the answer here and modified it so you get a List of types that aren't serializable. That way you can easily know 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 runs, nonSerializableTypes will have the list. There may be a better way of doing this than passing in an empty List to the recursive method. Someone correct me if so.

    0 讨论(0)
  • 2020-12-04 17:49

    This is an old question, that may 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 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)
    
    }
    
    0 讨论(0)
  • 2020-12-04 17:53

    Use Type.IsSerializable as others have pointed out.

    It's probably not worth attempting to reflect and check if all members in the object graph are serializable.

    A member could be declared as a serializable type, but in fact be instantiated as a derived type that is not serializable, as in the following contrived 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 can't in general be sure this will be true of all instances.

    0 讨论(0)
  • 2020-12-04 17:53

    The exception object might be serializable , but using an other exception which is not. This is what I just had with WCF System.ServiceModel.FaultException: FaultException is serializable but ExceptionDetail is not!

    So I am using 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 讨论(0)
  • 2020-12-04 17:56

    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 讨论(0)
  • 2020-12-04 17:58

    Here's a 3.5 variation that makes it available to all classes using an extension method.

    public static bool IsSerializable(this object obj)
    {
        if (obj is ISerializable)
            return true;
        return Attribute.IsDefined(obj.GetType(), typeof(SerializableAttribute));
    }
    
    0 讨论(0)
提交回复
热议问题