c# - Check if a type is serialzable

In WCF, primitives type are serialzable, and some commonly used types are also serialzable, but some types are not serialzable , and when this types to be used in wcf as the data contract for message, then you might get into trouble.

there are ways to determine if a type is serializable or an instance is serializable. To check if a type (on the type object itself)

typeof(T).IsSerializable

or you can check on the instance 

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

But be caereful that IsSerializable does not take into account the all types in the graph of objects being serialized for the serialable attribute.

You might want to check on that the reference page - how to check if an object is serializable in C#

Example of such is 

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


There are some general ways, such as put it onto Serialze and check for exception.
public static Stream Serialize(object source)
{
    IFormatter formatter = new BinaryFormatter();
    Stream stream = new MemoryStream();
    formatter.Serialize(stream, source);
    return stream;
}

public static T Deserialize<T>(Stream stream)
{
    IFormatter formatter = new BinaryFormatter();
    stream.Position = 0;
    return (T)formatter.Deserialize(stream);
}

public static T Clone<T>(object source)
{
    return Deserialize<T>(Serialize(source));
}
Serialize an object and deserizie it to get a clone and compare if they can be equal can tell if a type can be serialized.

there some other ways, like checking the types(generic types as well), 
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))));
    }


However, this suffer from the same problem of false positive when a derived member is not serialzable.

References:

how to check if an object is serializable in C#
How to unit test if my object is really serializable? 


你可能感兴趣的:(C#,WCF)