如何检查一个对象是否在C#中可序列化

我正在寻找一种简单的方法来检查,如果在C#中的对象是可序列化的。

正如我们所知,通过实现ISerializable接口或将[Serializable]放在类的顶部,可以使对象可序列化。

我正在寻找的是一个快速的方法来检查这一点,而不必反映类获取它的属性。 该界面将快速使用is语句。

使用@ Flard的build议,这是我已经提出的代码,尖叫是有一个更好的方法。

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

或者甚至更好的只是获取对象的types,然后使用types的IsSerializable属性:

 typeof(T).IsSerializable 

请记住,这似乎只是我们正在处理的类,如果类包含其他类,你可能想要检查他们所有或尝试序列化和等待错误@pb指出。

你有一个名为IsSerializableType类的可爱属性。

你将不得不在序列化的对象图中检查所有可序列化属性的types。 最简单的方法是尝试序列化对象并捕获exception。 (但这不是最干净的解决scheme)。 Type.IsSerializable和检查serializalbe属性不考虑graphics。

样品

 [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); } } 

这是一个老问题,可能需要更新.NET 3.5+。 如果类使用DataContract属性,则Type.IsSerializable实际上可以返回false。 这里是我使用的一个片段,如果它发臭,让我知道:)

 public static bool IsSerializable(this object obj) { Type t = obj.GetType(); return Attribute.IsDefined(t, typeof(DataContractAttribute)) || t.IsSerializable || (obj is IXmlSerializable) } 

像别人指出的那样使用Type.IsSerializable。

试图反映和检查对象图中的所有成员是否可序列化可能都不值得。

一个成员可以被声明为一个可序列化的types,但实际上被实例化为一个不可序列化的派生types,如下面这个人为的例子:

 [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 

因此,即使您确定您的types的特定实例是可序列化的,通常也不能确定这将在所有实例中都成立。

 Attribute.IsDefined(typeof (YourClass), typeof (SerializableAttribute)); 

可能涉及水下reflection,但最简单的方法?

这里有一个3.5的变化,使它可以使用扩展方法的所有类。

 public static bool IsSerializable(this object obj) { if (obj is ISerializable) return true; return Attribute.IsDefined(obj.GetType(), typeof(SerializableAttribute)); } 

我在这个问题上的答案和答案在这里,并修改它,所以你得到不可序列化的types列表。 这样你可以很容易地知道哪些标记。

  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)))); } 

然后你打电话给…

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

运行时,nonSerializableTypes将具有该列表。 比传递一个空列表到recursion方法可能有更好的方法。 如果有的话,有人纠正我。

exception对象可能是可序列化的,但是使用其他的exception。 这是我刚才与WCF System.ServiceModel.FaultException:FaultException是可序列化,但ExceptionDetail不是!

所以我使用以下内容:

 // 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); } 

我的解决scheme,在VB.NET中:

对象:

 ''' <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 

对于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