una sirve serializar serialización que para objetos net clase c# serialization

sirve - serializar una clase c#



Cómo verificar si un objeto es serializable en C# (9)

Estoy buscando una manera fácil de verificar si un objeto en C # es serializable.

Como sabemos, se puede serializar un objeto implementando la interfaz ISerializable o colocando el [Serializable] en la parte superior de la clase.

Lo que estoy buscando es una forma rápida de verificar esto sin tener que reflejar la clase para obtener sus atributos. La interfaz sería rápida usando una declaración de is .

Usando la sugerencia de @ Flard, este es el código que he ideado, gritar es que hay una mejor manera.

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

O incluso mejor solo obtenga el tipo de objeto y luego use la propiedad IsSerializable en el tipo:

typeof(T).IsSerializable

Recuerda, sin embargo, que esto parece ser solo la clase con la que estamos tratando si la clase contiene otras clases. Probablemente quieras revisarlas todas o intentar serializarlas y esperar por errores como lo señaló @pb.


Aquí hay una variación de 3.5 que lo hace disponible para todas las clases usando un método de extensión.

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


Deberá verificar todos los tipos en el gráfico de los objetos que se serializan para el atributo serializable. La forma más fácil es intentar serializar el objeto y capturar la excepción. (Pero esa no es la solución más limpia). Type.IsSerializable y comprobar el atributo serializalbe no tienen en cuenta el gráfico.

Muestra

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


El objeto de excepción puede ser serializable, pero usando otra excepción que no lo es. Esto es lo que acabo de tener con WCF System.ServiceModel.FaultException: ¡FaultException es serializable pero ExceptionDetail no lo es!

Entonces estoy usando lo siguiente:

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


Esta es una vieja pregunta, que puede necesitar ser actualizada para .NET 3.5+. Type.IsSerializable realmente puede devolver false si la clase usa el atributo DataContract. Aquí hay un fragmento que uso, si huele mal, házmelo saber :)

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


Mi solución, en VB.NET:

Para objetos:

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

Para los tipos:

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


Tiene una propiedad encantadora en la clase Type llamada IsSerializable .


Tomé la respuesta a esta pregunta y la respuesta here y la modifiqué para que obtuvieras una lista de tipos que no son serializables. De esta forma, puede saber fácilmente cuáles marcar.

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

Y luego lo llamas ...

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

Cuando se ejecuta, nonSerializableTypes tendrá la lista. Puede haber una forma mejor de hacer esto que pasar una Lista vacía al método recursivo. Alguien me corrige si es así.


Use Type.IsSerializable como otros señalaron.

Probablemente no valga la pena intentar reflejar y verificar si todos los miembros del gráfico objeto son serializables.

Un miembro se podría declarar como un tipo serializable, pero de hecho se instanciará como un tipo derivado que no es serializable, como en el siguiente ejemplo inventado:

[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

Por lo tanto, incluso si determina que una instancia específica de su tipo es serializable, en general no puede estar seguro de que esto sea cierto para todas las instancias.


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

Probablemente involucre la reflexión bajo el agua, ¿pero de la manera más simple?