views:

6512

answers:

9

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 interface or by placing the [Serializable] at the top of the class.

What I am looking for is a quick way to check this without having to reflect the class to get it's attributes. The interface would be quick using an is statement.

Using @Flard's suggestion this is the code that I have come up with, scream is there is a better way.

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

Or even better just get the type of the object and then use the IsSerializable property on the type:

typeof(T).IsSerializable

Remember though this this seems to only just the class that we are dealing with if the class contains other classes you probably want to check them all or try and serialize and wait for errors as @pb pointed out.

+2  A: 
Attribute.IsDefined(typeof (YourClass), typeof (SerializableAttribute));

Probably involves reflection underwater, but the most simple way?

Grad van Horck
OOOH! Awesome...
FryHard
+12  A: 

You're going to have to check all types in the graph of objects being serialized for the serializable attribute. The easiest way is to try to serialize the object and catch the exception. (But that's not the cleanest solution). Type.IsSerializable and checking for the serializalbe attribute don't take the graph into account.

Sample

[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);
    }
}
pb
+28  A: 

You have a lovely property on the Type class called IsSerializable.

leppie
A: 

Attribute.IsDefined(typeof(YourClass), typeof(SerializableAttribute)) is actually the only way. Because classes that uses default serialization does not implement any interfaces that you can check for.

Hallgrim
+2  A: 

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));
}
Michael Meadows
+4  A: 

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.

Joe
A: 

How about?

obj.GetType().IsSerializable
A: 

If you need to check if a value is serializable when setting the value in a property you can also use

... Set{ if (value.GetType().IsSerializable) { YourProp = value; } }

Juan Zamora M
+1  A: 

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)

}
Mike_G