我正在寻找一种简单的方法来检查C#中的对象是否可序列化.
我们知道,通过实现ISerializable接口或将[Serializable]放在类的顶部,可以使对象可序列化.
我正在寻找的是一种快速检查方法,而无需反映类以获得它的属性.接口可以快速使用is语句.
使用@Flard的建议这是我提出的代码,尖叫是有更好的方法.
private static bool IsSerializable(T obj) { return ((obj is ISerializable) || (Attribute.IsDefined(typeof (T), typeof (SerializableAttribute)))); }
或者甚至更好地获取对象的类型,然后在类型上使用IsSerializable属性:
typeof(T).IsSerializable
请记住,这似乎只是我们正在处理的类,如果类包含其他类,您可能想要检查它们或尝试序列化并等待错误,如@pb指出的那样.
你在这个Type
班上有一个可爱的财产IsSerializable
.
您将不得不检查序列化为serializable属性的对象图中的所有类型.最简单的方法是尝试序列化对象并捕获异常.(但这不是最干净的解决方案).Type.IsSerializable和检查serializalbe属性不会考虑图形.
样品
[Serializable] public class A { public B B = new B(); } public class B { public string a = "b"; } [Serializable] public class C { public D D = 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.
可能不值得尝试反映并检查对象图中的所有成员是否可序列化.
可以将成员声明为可序列化类型,但实际上将其实例化为不可序列化的派生类型,如下面的设计示例所示:
[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
因此,即使您确定类型的特定实例是可序列化的,通常也不能确定所有实例都是如此.
Attribute.IsDefined(typeof (YourClass), typeof (SerializableAttribute));
可能涉及水下反射,但最简单的方法呢?
这是一个3.5变体,它使用扩展方法使所有类都可用.
public static bool IsSerializable(this object obj) { if (obj is ISerializable) return true; return Attribute.IsDefined(obj.GetType(), typeof(SerializableAttribute)); }