/*
OpenNxSerialization Framework
Copyright (C) 2006 - 2008 "NeXtreme Innovations"
[The Next Xtreme in ingenuity]
This program is free software, distributed under the terms of
the GNU General Public License Version 2. See the License file
at the top of the source tree.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using NeXtreme.OpenNxSerialization.IO;
namespace NeXtreme.OpenNxSerialization.Surrogates
{
/// <summary>
/// Surrogate for <typeparamref name="T[]"/> type, where <typeparamref name="T"/> is a primitive type.
/// </summary>
sealed class NxPrimitiveArraySerializationSurrogate<T> : NxSerializationSurrogate, INxBuiltinSerializationSurrogate
{
private readonly int mTypeSize;
public NxPrimitiveArraySerializationSurrogate()
: base(typeof(T[]))
{
mTypeSize = Buffer.ByteLength(new T[1]);
}
public override object Instantiate(INxBinaryReader reader)
{
int length = reader.ReadInt32();
return new T[length];
}
public override object ReadDirect(INxBinaryReader reader, object graph)
{
T[] array = (T[])graph;
int length = array.Length * mTypeSize;
byte[] contents = new byte[length];
reader.Read(contents, 0, length);
Buffer.BlockCopy(contents, 0, array, 0, length);
return array;
}
public override void WriteDirect(INxBinaryWriter writer, object graph)
{
T[] array = (T[])graph;
byte[] buffer = new byte[4];
Buffer.BlockCopy(BitConverter.GetBytes(array.Length), 0, buffer, 0, 4);
writer.Write(buffer, 0, 4);
int length = array.Length * mTypeSize;
buffer = new byte[length];
Buffer.BlockCopy(array, 0, buffer, 0, length);
writer.Write(buffer, 0, length);
}
}
/// <summary>
/// Surrogate for generic <see cref="System.Array"/> types.
/// </summary>
sealed class NxArraySerializationSurrogate : NxSerializationSurrogate, INxBuiltinSerializationSurrogate
{
public NxArraySerializationSurrogate(Type type) : base(type) { }
public override object Instantiate(INxBinaryReader reader)
{
int length = reader.ReadInt32();
return Array.CreateInstance(ActualType.GetElementType(), length);
}
public override object ReadDirect(INxBinaryReader reader, object graph)
{
Array array = (Array)graph;
for (int i = 0; i < array.Length; i++)
array.SetValue(reader.ReadObject(), i);
return array;
}
public override void WriteDirect(INxBinaryWriter writer, object graph)
{
Array array = (Array)graph;
writer.Write(array.Length);
for (int i = 0; i < array.Length; i++)
writer.WriteObject(array.GetValue(i));
}
}
/// <summary>
/// Surrogate for generic <see cref="System.Array"/> types.
/// </summary>
sealed class NxGenericArraySerializationSurrogate<T> : NxSerializationSurrogate, INxBuiltinSerializationSurrogate
{
public NxGenericArraySerializationSurrogate() : base(typeof(T[])) { }
public override object Instantiate(INxBinaryReader reader)
{
int length = reader.ReadInt32();
return new T[length];
}
/// <summary>
/// Read an object of type <see cref="INxSerializationSurrogate.ActualType"/> from the stream reader.
/// A fresh instance of the object is passed as parameter.
/// The surrogate should populate fields in the object from data on the stream
/// </summary>
/// <param name="reader">stream reader</param>
/// <param name="graph">a fresh instance of the object that the surrogate must deserialize</param>
/// <returns>object read from the stream reader</returns>
public override object ReadDirect(INxBinaryReader reader, object graph)
{
T[] array = (T[])graph;
for (int i = 0; i < array.Length; i++)
array[i] = (T)reader.ReadObject();
return array;
}
/// <summary>
/// Write an object of type <see cref="INxSerializationSurrogate.ActualType"/> to the stream writer
/// </summary>
/// <param name="writer">stream writer</param>
/// <param name="graph">object to be written to the stream reader</param>
public override void WriteDirect(INxBinaryWriter writer, object graph)
{
T[] array = (T[])graph;
writer.Write(array.Length);
for (int i = 0; i < array.Length; i++)
writer.WriteObject(array[i]);
}
}
/// <summary>
/// Surrogate for types that inherit from <see cref="System.Collections.IList"/>.
/// </summary>
sealed class NxIListSerializationSurrogate : NxSerializationSurrogate, INxBuiltinSerializationSurrogate
{
public NxIListSerializationSurrogate(Type type) : base(type) { }
/// <summary>
/// Creates instance of <see cref="INxSerializationSurrogate.ActualType"/>. Calls the default constructor and returns
/// the object. There must be a default constructor even though it is private.
/// </summary>
/// <returns>Object that this surrogate must deserialize</returns>
/// <exception cref="InvalidOperationException">when <see cref="INxSerializationSurrogate.ActualType"/> is non-creatable</exception>
public override object CreateTypeInstance()
{
return Activator.CreateInstance(ActualType,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance,
null, null, null, null);
}
public override object ReadDirect(INxBinaryReader reader, object graph)
{
int length = reader.ReadInt32();
IList list = (IList)graph;
for (int i = 0; i < length; i++)
list.Add(reader.ReadObject());
return list;
}
public override void WriteDirect(INxBinaryWriter writer, object graph)
{
IList list = (IList)graph;
writer.Write(list.Count);
for (int i = 0; i < list.Count; i++)
writer.WriteObject(list[i]);
}
}
/// <summary>
/// Surrogate for <typeparamref name="T"/> types.
/// </summary>
sealed class NxGenericIListSerializationSurrogate<T> : NxSerializationSurrogate, INxBuiltinSerializationSurrogate
{
public NxGenericIListSerializationSurrogate(Type type) : base(type) { }
/// <summary>
/// Creates instance of <see cref="INxSerializationSurrogate.ActualType"/>. Calls the default constructor and returns
/// the object. There must be a default constructor even though it is private.
/// </summary>
/// <returns>Object that this surrogate must deserialize</returns>
/// <exception cref="InvalidOperationException">when <see cref="INxSerializationSurrogate.ActualType"/> is non-creatable</exception>
public override object CreateTypeInstance()
{
return Activator.CreateInstance(ActualType,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance,
null, null, null, null);
}
/// <summary>
/// Read an object of type <see cref="INxSerializationSurrogate.ActualType"/> from the stream reader.
/// A fresh instance of the object is passed as parameter.
/// The surrogate should populate fields in the object from data on the stream
/// </summary>
/// <param name="reader">stream reader</param>
/// <param name="graph">a fresh instance of the object that the surrogate must deserialize</param>
/// <returns>object read from the stream reader</returns>
public override object ReadDirect(INxBinaryReader reader, object graph)
{
int length = reader.ReadInt32();
IList<T> list = (IList<T>)graph;
for (int i = 0; i < length; i++)
list.Add(reader.ReadObjectAs<T>());
return list;
}
/// <summary>
/// Write an object of type <see cref="INxSerializationSurrogate.ActualType"/> to the stream writer
/// </summary>
/// <param name="writer">stream writer</param>
/// <param name="graph">object to be written to the stream reader</param>
public override void WriteDirect(INxBinaryWriter writer, object graph)
{
IList<T> list = (IList<T>)graph;
writer.Write(list.Count);
for (int i = 0; i < list.Count; i++)
writer.WriteObjectAs<T>(list[i]);
}
}
/// <summary>
/// Surrogate for types that inherit from <see cref="System.Collections.IDictionary"/>.
/// </summary>
sealed class NxIDictionarySerializationSurrogate : NxSerializationSurrogate, INxBuiltinSerializationSurrogate
{
public NxIDictionarySerializationSurrogate(Type type) : base(type) { }
/// <summary>
/// Creates instance of <see cref="INxSerializationSurrogate.ActualType"/>. Calls the default constructor and returns
/// the object. There must be a default constructor even though it is private.
/// </summary>
/// <returns>Object that this surrogate must deserialize</returns>
/// <exception cref="InvalidOperationException">when <see cref="INxSerializationSurrogate.ActualType"/> is non-creatable</exception>
public override object CreateTypeInstance()
{
return Activator.CreateInstance(ActualType,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance,
null, null, null, null);
}
public override object ReadDirect(INxBinaryReader reader, object graph)
{
int length = reader.ReadInt32();
IDictionary dict = (IDictionary)graph;
for (int i = 0; i < length; i++)
{
object key = reader.ReadObject();
object value = reader.ReadObject();
dict.Add(key, value);
}
return dict;
}
public override void WriteDirect(INxBinaryWriter writer, object graph)
{
IDictionary dict = (IDictionary)graph;
writer.Write(dict.Count);
for (IDictionaryEnumerator i = dict.GetEnumerator(); i.MoveNext(); )
{
writer.WriteObject(i.Key);
writer.WriteObject(i.Value);
}
}
}
/// <summary>
/// Surrogate for KeyValuePair structure with the specified key and value.
/// </summary>
sealed class NxKeyValuePairSerializationSurrogate<K, V> : NxSerializationSurrogateBase, INxSerializationSurrogate, INxBuiltinSerializationSurrogate
{
public NxKeyValuePairSerializationSurrogate() : base(typeof(KeyValuePair<K, V>)) { }
/// <summary>
/// Read an object of type <see cref="INxSerializationSurrogate.ActualType"/> from the stream reader
/// </summary>
/// <param name="reader">The reader from which the data is deserialized</param>
/// <returns>object read from the stream reader</returns>
public object Read(INxBinaryReader reader)
{
K key = reader.ReadObjectAs<K>();
V value = reader.ReadObjectAs<V>();
return new KeyValuePair<K, V>(key, value);
}
/// <summary>
/// Write an object of type <see cref="INxSerializationSurrogate.ActualType"/> to the stream writer
/// </summary>
/// <param name="writer">The writer onto which the specified graph is serialized</param>
/// <param name="graph">The root of the object graph to be serialized</param>
public void Write(INxBinaryWriter writer, object graph)
{
KeyValuePair<K, V> pair = (KeyValuePair<K, V>)graph;
writer.WriteObjectAs<K>(pair.Key);
writer.WriteObjectAs<V>(pair.Value);
}
}
/// <summary>
/// Surrogate for generic collection of key/value pairs.
/// </summary>
sealed class NxGenericIDictionarySerializationSurrogate<K, V> : NxSerializationSurrogate, INxBuiltinSerializationSurrogate
{
public NxGenericIDictionarySerializationSurrogate(Type type) : base(type) { }
/// <summary>
/// Creates instance of <see cref="INxSerializationSurrogate.ActualType"/>. Calls the default constructor and returns
/// the object. There must be a default constructor even though it is private.
/// </summary>
/// <returns>Object that this surrogate must deserialize</returns>
/// <exception cref="InvalidOperationException">when <see cref="INxSerializationSurrogate.ActualType"/> is non-creatable</exception>
public override object CreateTypeInstance()
{
return Activator.CreateInstance(ActualType,
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance,
null, null, null, null);
}
/// <summary>
/// Read an object of type <see cref="INxSerializationSurrogate.ActualType"/> from the stream reader.
/// A fresh instance of the object is passed as parameter.
/// The surrogate should populate fields in the object from data on the stream
/// </summary>
/// <param name="reader">stream reader</param>
/// <param name="graph">a fresh instance of the object that the surrogate must deserialize</param>
/// <returns>object read from the stream reader</returns>
public override object ReadDirect(INxBinaryReader reader, object graph)
{
int length = reader.ReadInt32();
IDictionary<K, V> dict = (IDictionary<K, V>)graph;
for (int i = 0; i < length; i++)
{
K key = reader.ReadObjectAs<K>();
V value = reader.ReadObjectAs<V>();
dict.Add(key, value);
}
return dict;
}
/// <summary>
/// Write an object of type <see cref="INxSerializationSurrogate.ActualType"/> to the stream writer
/// </summary>
/// <param name="writer">stream writer</param>
/// <param name="graph">object to be written to the stream reader</param>
public override void WriteDirect(INxBinaryWriter writer, object graph)
{
IDictionary<K, V> dict = (IDictionary<K, V>)graph;
writer.Write(dict.Count);
for (IEnumerator<KeyValuePair<K, V>> i = dict.GetEnumerator(); i.MoveNext(); )
{
writer.WriteObjectAs<K>(i.Current.Key);
writer.WriteObjectAs<V>(i.Current.Value);
}
}
}
}