Domanda

Sto cercando un modo semplice per verificare se un oggetto in C# è serializzabile.

Come sappiamo si fanno un oggetto serializzabile grazie all'attuazione del ISerializable interfaccia o mettendo il [Serializable] al top della classe.

Quello che sto cercando è un modo rapido per controllare questo, senza dover riflettere la classe per ottenere gli attributi.L'interfaccia potrebbe essere rapido utilizzando un è istruzione.

Con @Flard suggerimento questo è il codice che ho fornito, urlare è che c'è un modo migliore.

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

O ancora meglio per ottenere il tipo di oggetto e quindi utilizzare il IsSerializable proprietà del tipo:

typeof(T).IsSerializable

Ricorda, però, questo sembra solo la classe che abbiamo a che fare con se la classe contiene altre classi, probabilmente si desidera controllare tutti e di provare a serializzare e attendere per gli errori, come @pb sottolineato.

È stato utile?

Soluzione

Hai una bella proprietà su la Type classe chiamata IsSerializable.

Altri suggerimenti

Si sta andando ad avere per controllare tutti i tipi nel grafico di oggetti serializzati per l'attributo serializable.Il modo più semplice è quello di cercare di serializzare l'oggetto e catturare l'eccezione.(Ma non è la soluzione più pulita).Tipo.IsSerializable e il controllo per la serializalbe attributo non prendere il grafico in considerazione.

Campione

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

Questa è una vecchia questione, che possono avere bisogno di essere aggiornato per .NET 3.5+.Tipo.IsSerializable può effettivamente restituisce false se la classe utilizza la DataContract attributo.Ecco un frammento di utilizzare, se puzza, fammi sapere :)

public static bool IsSerializable(this object obj)
{
    Type t = obj.GetType();

     return  Attribute.IsDefined(t, typeof(DataContractAttribute)) || t.IsSerializable || (obj is IXmlSerializable)

}

Questo Tipo Di Uso.IsSerializable come altri hanno sottolineato.

Probabilmente non vale la pena di tentare di riflettere e di controllare se tutti i membri di un oggetto grafico sono serializzabili.

Un membro può essere dichiarato come serializzabile tipo, ma in realtà, per creare un'istanza di un tipo derivato che non è serializzabile, come nel seguente esempio artificioso:

[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

Pertanto, anche se si determina che una specifica istanza di un tipo è serializzabile, non è possibile, in generale, essere sicuri che questo sarà vero per tutti i casi.

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

Probabilmente comporta la riflessione in acqua, ma il modo più semplice?

Ecco un 3.5 variazione che si rende disponibile per tutte le classi, utilizzando un metodo di estensione.

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

Ho preso la risposta a questa domanda e la risposta qui e modificato in modo che si ottiene un Elenco di tipi che non sono serializzabili.In questo modo si può facilmente sapere quali marco.

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

E quindi è chiamare...

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

Quando viene eseguito, nonSerializableTypes avrà l'elenco.Ci può essere un modo migliore di fare questo quello che passa in una Lista vuota di un metodo ricorsivo.Qualcuno mi corregga se è così.

L'oggetto eccezione potrebbe essere serializzabile , ma usando un'altra eccezione che non è.Questo è quello che ho appena avuto con WCF Sistema.ServiceModel.FaultException:FaultException è serializzabile, ma ExceptionDetail non è!

Così sto usando il seguente:

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

La mia soluzione, in VB.NET:

Per Gli Oggetti:

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

Per I Tipi:

''' <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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top