/*
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.Runtime.Serialization;
using NeXtreme.OpenNxSerialization.Surrogates;
namespace NeXtreme.OpenNxSerialization.Native
{
/// <summary>
/// Provides methods to register <see cref="INxSerializable"/> implementations
/// utilizing available surrogates.
/// </summary>
public sealed class NxFormatterServices
{
private static NxFormatterServices msDefault;
private INxTypeSurrogateSelector mSurrogateSelector;
/// <summary>
/// Constructor
/// </summary>
public NxFormatterServices()
{
this.mSurrogateSelector = NxTypeSurrogateSelectorNative.Default;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="surrogateSelector">Specifies a <see cref="INxTypeSurrogateSelector"/> object
/// to use as default selector</param>
public NxFormatterServices(INxTypeSurrogateSelector surrogateSelector)
{
if (surrogateSelector == null)
throw new ArgumentNullException("surrogateSelector");
this.mSurrogateSelector = surrogateSelector;
}
/// <summary>
/// returns the default instance of <see cref="NxFormatterServices"/>
/// </summary>
public static NxFormatterServices Default
{
get
{
if (msDefault == null)
msDefault = new NxFormatterServices();
return msDefault;
}
}
/// <summary>
/// Returns the current type surrogate selector object
/// </summary>
/// <value>The current <see cref="INxTypeSurrogateSelector"/> object</value>
public INxTypeSurrogateSelector SurrogateSelector
{
get { return mSurrogateSelector; }
set { mSurrogateSelector = value; }
}
#region / INxSerializable specific /
/// <summary>
/// Registers a type that implements <see cref="INxSerializable"/> with the system. If the
/// type is an array of <see cref="INxSerializable"/>s appropriate surrogates for arrays
/// and the element type are also registered.
/// </summary>
/// <param name="type">type that implements <see cref="INxSerializable"/></param>
/// <param name="typeHandle">specified HARD handle for type</param>
/// <exception cref="ArgumentNullException">If <paramref name="type"/> is null</exception>
/// <exception cref="ArgumentException">
/// If the <paramref name="type"/> is already registered or when no appropriate surrogate
/// is found for the specified <paramref name="type"/>.
/// </exception>
public void RegisterKnownType(Type type, short typeHandle)
{
if (type == null) throw new ArgumentNullException("type");
if (mSurrogateSelector.GetSurrogateForType(type, true) != null)
throw new ArgumentException(Resources.Type_AlreadyRegistered);
INxSerializationSurrogate surrogate = SelectBestSurrogate(type);
if (surrogate == null)
throw new ArgumentException(Resources.Surrogates_NotFound);
System.Diagnostics.Debug.WriteLine("Registered surrogate for type " + type.FullName);
mSurrogateSelector.Register(surrogate, typeHandle);
}
/// <summary>
/// Registers a type that implements <see cref="INxSerializable"/> with the system. If the
/// type is an array of <see cref="INxSerializable"/>s appropriate surrogates for arrays
/// and the element type are also registered.
/// </summary>
/// <param name="type">type that implements <see cref="INxSerializable"/></param>
/// <exception cref="ArgumentNullException">If <paramref name="type"/> is null.
/// </exception>
/// <exception cref="ArgumentException">
/// If the <paramref name="type"/> is already registered or when no appropriate surrogate
/// is found for the specified <paramref name="type"/>.
/// </exception>
public void RegisterKnownType(Type type)
{
if (type == null) throw new ArgumentNullException("type");
if (mSurrogateSelector.GetSurrogateForType(type, true) != null)
throw new ArgumentException(Resources.Type_AlreadyRegistered);
INxSerializationSurrogate surrogate = SelectBestSurrogate(type);
if (surrogate == null)
throw new ArgumentException(Resources.Surrogates_NotFound);
System.Diagnostics.Debug.WriteLine("Registered surrogate for type " + type.FullName);
mSurrogateSelector.Register(surrogate);
}
/// <summary>
/// Unregisters the surrogate for the specified type that implements
/// <see cref="INxSerializable"/> from the system.
/// </summary>
/// <param name="type">the specified type</param>
public void UnregisterKnownType(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
INxSerializationSurrogate surrogate = mSurrogateSelector.GetSurrogateForType(type, true);
if (surrogate != null)
{
mSurrogateSelector.Unregister(surrogate);
System.Diagnostics.Debug.WriteLine("Unregistered surrogate for type " + type.FullName);
}
}
/// <summary>
/// Finds and returns the best surrogate responsible for serializing the specified <paramref name="type"/>
/// </summary>
/// <param name="type">the given <see cref="Type"/>, whose surrogate is returned</param>
/// <returns>instance of <see cref="INxSerializationSurrogate"/></returns>
private static INxSerializationSurrogate SelectBestSurrogate(Type type)
{
INxSerializationSurrogate surrogate = null;
if (type.IsMarshalByRef)
{
surrogate = new NxMarshalByRefObjectSerializationSurrogate(type);
}
else if (typeof(IDictionary).IsAssignableFrom(type))
{
if (type.IsGenericType)
{
surrogate = (INxSerializationSurrogate)
NxSurrogateHelper.CreateGenericTypeInstance(typeof(NxGenericIDictionarySerializationSurrogate<,>), type.GetGenericArguments());
}
else
{
surrogate = new NxIDictionarySerializationSurrogate(type);
}
}
else if (type.IsArray)
{
surrogate = new NxArraySerializationSurrogate(type);
}
else if (typeof(IList).IsAssignableFrom(type))
{
if (type.IsGenericType)
{
surrogate = (INxSerializationSurrogate)
NxSurrogateHelper.CreateGenericTypeInstance(typeof(NxGenericIListSerializationSurrogate<>), type.GetGenericArguments());
}
else
{
surrogate = new NxIListSerializationSurrogate(type);
}
}
else if (typeof(INxSerializable).IsAssignableFrom(type))
{
surrogate = new NxINxSerializableSerializationSurrogate(type);
}
else if (typeof(ISerializable).IsAssignableFrom(type))
{
surrogate = new NxISerializableSerializationSurrogate(type);
}
else if (typeof(Enum).IsAssignableFrom(type))
{
surrogate = new NxEnumSerializationSurrogate(type);
}
return surrogate;
}
#endregion
}
}