December 14, 2012

Binary Serialization

Some binary serialization links:
Version Tolerant Serialization
Format Your Way to Success with the .NET Framework Versions 1.1 and 2.0 - Used some of the classes here to develop the BinarySerializer class below
Advanced serialization tips
Custom Serialization
Here is a sample binary serialisation class
private class BinarySerializer
{
    internal interface IGenericFormatter
    {
        T Deserialize<T>(Stream serializationStream);
        void Serialize<T>(Stream serializationStream, T graph);
    }

    internal class GenericFormatter<F> : IGenericFormatter 
     where F : IFormatter, new()
    {
        IFormatter m_Formatter = new F();

        public T Deserialize<T>(Stream serializationStream)
        {
            return (T)m_Formatter.Deserialize(serializationStream);
        }
        public void Serialize<T>(Stream serializationStream, T graph)
        {
            m_Formatter.Serialize(serializationStream, graph);
        }
    }

    internal class GenericBinaryFormatter : 
     GenericFormatter<BinaryFormatter> { }

    public void SerializeToFile<Type>(Type obj, string filePath)
    {
        IGenericFormatter formatter = new GenericBinaryFormatter();
        using (Stream stream = new FileStream(
            filePath, FileMode.Create, FileAccess.ReadWrite))
        {
            formatter.Serialize(stream, obj);
            stream.Close();
        }
    }

    public Type DeserializeFromFile<Type>(string filePath)
    {
        Type res = default(Type);
        if (File.Exists(filePath))
        {
            IGenericFormatter formatter = new GenericBinaryFormatter();
            using (Stream stream = new FileStream(
                filePath, FileMode.Open, FileAccess.ReadWrite))
            {
                res = formatter.Deserialize<Type>(stream);
                stream.Close();
            }
        }
        return res;
    }

    public byte[] SerializeToByteArray<Type>(Type obj)
    {
        byte[] res = null;
        IGenericFormatter formatter = new GenericBinaryFormatter();
        using (MemoryStream stream = new MemoryStream())
        {
            formatter.Serialize(stream, obj);
            res = stream.ToArray();
            stream.Close();
        }
        return res;
    }

    public Type DeserializeFromByteArray<Type>(byte[] bytes)
    {
        Type res = default(Type);
        if ((bytes != null) && (bytes.Length > 0))
        {
            IGenericFormatter formatter = new GenericBinaryFormatter();
            using (MemoryStream stream = new MemoryStream(bytes))
            {
                res = formatter.Deserialize<Type>(stream);
                stream.Close();
            }
        }
        return res;
    }

    public Type Clone<Type>(Type obj)
    {
        byte[] bytes = SerializeToByteArray<Type>(obj);
        Type res = DeserializeFromByteArray<Type>(bytes);
        return res;
    }
}
Can be used with this code to test binary serialisation of something
private static Type SerializeDeserialize<Type>(Type src) 
    where Type
{
    BinarySerializer bs = new BinarySerializer();
    byte[] bytes = bs.SerializeToByteArray<Type>(src);
    // Use these lines to create binary serialization files, 
    //string filePath = Path.Combine(Path.GetTempPath(), "SerialisedObject.bin");
    //File.WriteAllBytes(filePath, bytes);
    Type ds = bs.DeserializeFromByteArray<Type>(bytes);
    return ds;
}

December 13, 2012

Codeplex library to compare .NET objects

Codeplex library to compare .NET objects can be found here
Here is a sample usage of the ObjectCompare class:
// An equality comparator for XXX. Uses a 3rd party ObjectComparer utility class.
// Objects are considered equal if all their public properties and fields are equal
// UNUSUALLY ReferenceEquals fails when the 2 references are equal
// We should not be comparing the same objects in these
// tests
static bool XXXsAreEqual(XXX ds1, XXX ds2, List<string> elementsToIgnore = null)
{
    // Check for null values
    if (ds1 == null)
    {
        return (ds2 == null);
    }
    else if (ds2 == null)
    {
        return false;
    }

    // Check for NOT reference equals
    if (object.ReferenceEquals(ds1, ds2))
        return false; // This should NOT happen in these unit tests, fail if it does!

    // compare run-time types.
    if (ds1.GetType() != ds2.GetType())
        return false;

    // Ensure all public non-static properties and fields are equal
    var objectComparator = new ObjectCompare();
    objectComparator.CompareStaticFields = false;
    objectComparator.CompareStaticProperties = false;
    objectComparator.ComparePrivateProperties = false;
    objectComparator.ComparePrivateFields = false;
    objectComparator.CompareFields = true;
    objectComparator.CompareChildren = true;
    objectComparator.CompareReadOnly = true;
    objectComparator.CompareProperties = true;
    objectComparator.Caching = true;
    objectComparator.AutoClearCache = true;
    objectComparator.IgnoreObjectTypes = false; // Already done this above
    objectComparator.MaxDifferences = 1;
    objectComparator.ElementsToIgnore = elementsToIgnore ?? 
                                                new List<string>();

    bool res = objectComparator.Compare(ds1, ds2);
    // If this method fails, check the cause here!
    List<string> causeOfFailure = objectComparator.Differences; 
    if (causeOfFailure.Count > 0)
    {
        Debug.Write("Equality failure caused by following properties/fields: ");
        string failedOn = string.Join(", ", causeOfFailure.ToArray());
        Debug.WriteLine(failedOn);
    }
    return res;
}
To convert this to an equals operator of some kind you would have to fix the reference equals part to return true when the 2 references are equal.