Skip to content
Permalink
Browse files

Add untyped serializer factory and retrieval wrapper for Serializatio…

…nContext.GetSerailizer toward MessagePackSerializer class.
  • Loading branch information...
yfakariya committed Sep 6, 2012
1 parent ea657dd commit 8c8b4d7a4f74b96156226a4034f95b30f6a69d2d
@@ -338,6 +338,9 @@
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackObject.cs">
<Link>Serialization\Metadata\_MessagePackObject.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackSerializer.cs">
<Link>Serialization\Metadata\_MessagePackSerializer.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_NotImplementedException.cs">
<Link>Serialization\Metadata\_NotImplementedException.cs</Link>
</Compile>
@@ -270,6 +270,9 @@
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackObject.cs">
<Link>Serialization\Metadata\_MessagePackObject.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackSerializer.cs">
<Link>Serialization\Metadata\_MessagePackSerializer.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_NotImplementedException.cs">
<Link>Serialization\Metadata\_NotImplementedException.cs</Link>
</Compile>
@@ -290,6 +290,9 @@
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackObject.cs">
<Link>Serialization\Metadata\_MessagePackObject.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackSerializer.cs">
<Link>Serialization\Metadata\_MessagePackSerializer.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_NotImplementedException.cs">
<Link>Serialization\Metadata\_NotImplementedException.cs</Link>
</Compile>
@@ -270,6 +270,9 @@
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackObject.cs">
<Link>Serialization\Metadata\_MessagePackObject.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackSerializer.cs">
<Link>Serialization\Metadata\_MessagePackSerializer.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_NotImplementedException.cs">
<Link>Serialization\Metadata\_NotImplementedException.cs</Link>
</Compile>
@@ -243,6 +243,9 @@
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackObject.cs">
<Link>Serialization\Metadata\_MessagePackObject.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_MessagePackSerializer.cs">
<Link>Serialization\Metadata\_MessagePackSerializer.cs</Link>
</Compile>
<Compile Include="..\MsgPack\Serialization\Metadata\_Nullable`1.cs">
<Link>Serialization\Metadata\_Nullable`1.cs</Link>
</Compile>
@@ -175,6 +175,7 @@
<Compile Include="Serialization\Metadata\_Enumerable.cs" />
<Compile Include="Serialization\Metadata\_IDictionaryEnumerator.cs" />
<Compile Include="Serialization\Metadata\_IEnumreator.cs" />
<Compile Include="Serialization\Metadata\_MessagePackSerializer.cs" />
<Compile Include="Serialization\Metadata\_SerializationContext.cs" />
<Compile Include="Serialization\Metadata\_String.cs" />
<Compile Include="Serialization\Metadata\_MessagePackObject.cs" />
@@ -19,11 +19,15 @@
#endregion -- License Terms --

using System;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
#if SILVERLIGHT
using System.Collections.Generic;
#else
using System.Collections.Concurrent;
#endif
using System.Diagnostics.Contracts;
#if NETFX_CORE
using System.Linq.Expressions;
#endif
#if !NETFX_CORE
using MsgPack.Serialization.EmittingSerializers;
#endif
@@ -47,6 +51,8 @@ public static class MessagePackSerializer
/// </returns>
public static MessagePackSerializer<T> Create<T>()
{
Contract.Ensures( Contract.Result<MessagePackSerializer<T>>() != null );

return MessagePackSerializer.Create<T>( SerializationContext.Default );
}

@@ -100,5 +106,212 @@ public static MessagePackSerializer<T> Create<T>( SerializationContext context )
return new AutoMessagePackSerializer<T>( context, builderProvider );
}

#if !SILVERLIGHT
private static readonly ConcurrentDictionary<Type, Func<SerializationContext, IMessagePackSerializer>> _creatorCache = new ConcurrentDictionary<Type, Func<SerializationContext, IMessagePackSerializer>>();
#else
private static readonly object _syncRoot = new object();
private static readonly Dictionary<Type, Func<SerializationContext, IMessagePackSerializer>> _creatorCache = new Dictionary<Type, Func<SerializationContext, IMessagePackSerializer>>();
#endif

/// <summary>
/// Creates new <see cref="IMessagePackSerializer"/> instance with <see cref="SerializationContext.Default"/>.
/// </summary>
/// <param name="targetType">Target type.</param>
/// <returns>
/// New <see cref="IMessagePackSerializer"/> instance to serialize/deserialize the object tree which the top is <paramref name="targetType"/>.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="targetType"/> is <c>null</c>.
/// </exception>
/// <remarks>
/// To avoid boxing and strongly typed API is prefered, use <see cref="Create{T}()"/> instead when possible.
/// </remarks>
public static IMessagePackSerializer Create( Type targetType )
{
return MessagePackSerializer.Create( targetType, SerializationContext.Default );
}

/// <summary>
/// Creates new <see cref="IMessagePackSerializer"/> instance with specified <see cref="SerializationContext"/>.
/// </summary>
/// <param name="targetType">Target type.</param>
/// <param name="context">
/// <see cref="SerializationContext"/> to store known/created serializers.
/// </param>
/// <returns>
/// New <see cref="IMessagePackSerializer"/> instance to serialize/deserialize the object tree which the top is <paramref name="targetType"/>.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="targetType"/> is <c>null</c>.
/// Or, <paramref name="context"/> is <c>null</c>.
/// </exception>
/// <remarks>
/// To avoid boxing and strongly typed API is prefered, use <see cref="Create{T}(SerializationContext)"/> instead when possible.
/// </remarks>
public static IMessagePackSerializer Create( Type targetType, SerializationContext context )
{
if ( targetType == null )
{
throw new ArgumentNullException( "targetType" );
}

if ( context == null )
{
throw new ArgumentNullException( "context" );
}

Contract.Ensures( Contract.Result<IMessagePackSerializer>() != null );

#if NETFX_CORE
var factory =
_creatorCache.GetOrAdd(
targetType,
type =>
{
var contextParameter = Expression.Parameter( typeof( SerializationContext ), "context" );
// Utilize covariance of delegate.
return
Expression.Lambda<Func<SerializationContext, IMessagePackSerializer>>(
Expression.Call(
contextParameter,
Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod( type )
),
contextParameter
).Compile();
}
);
#elif SILVERLIGHT
Func<SerializationContext, IMessagePackSerializer> factory;

lock ( _syncRoot )
{
_creatorCache.TryGetValue( targetType, out factory );
}

if ( factory == null )
{
// Utilize covariance of delegate.
factory =
Delegate.CreateDelegate(
typeof( Func<SerializationContext, IMessagePackSerializer> ),
Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod( targetType )
) as Func<SerializationContext, IMessagePackSerializer>;

lock ( _syncRoot )
{
_creatorCache[ targetType ] = factory;
}
}
#else
var factory =
_creatorCache.GetOrAdd(
targetType,
type =>
// Utilize covariance of delegate.
Delegate.CreateDelegate(
typeof( Func<SerializationContext, IMessagePackSerializer> ),
Metadata._MessagePackSerializer.Create1_Method.MakeGenericMethod( type )
) as Func<SerializationContext, IMessagePackSerializer>
);
#endif
return factory( context );
}

/// <summary>
/// Gets a <see cref="MessagePackSerializer{T}"/> instance stored in <see cref="SerializationContext.Default"/>.
/// If a serializer for <typeparamref name="T"/> is not stored, <see cref="Create{T}()"/> will be called automatically.
/// </summary>
/// <typeparam name="T">Target type.</typeparam>
/// <returns>
/// New <see cref="MessagePackSerializer{T}"/> instance to serialize/deserialize the object tree which the top is <typeparamref name="T"/>.
/// </returns>
public static MessagePackSerializer<T> Get<T>()
{
Contract.Ensures( Contract.Result<MessagePackSerializer<T>>() != null );

return Get<T>( SerializationContext.Default );
}

/// <summary>
/// Gets a <see cref="MessagePackSerializer{T}"/> instance stored in the specified <see cref="SerializationContext"/>.
/// If a serializer for <typeparamref name="T"/> is not stored, <see cref="Create{T}(SerializationContext)"/> will be called automatically.
/// </summary>
/// <typeparam name="T">Target type.</typeparam>
/// <param name="context">
/// <see cref="SerializationContext"/> to store known/created serializers.
/// </param>
/// <returns>
/// New <see cref="MessagePackSerializer{T}"/> instance to serialize/deserialize the object tree which the top is <typeparamref name="T"/>.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="context"/> is <c>null</c>.
/// </exception>
public static MessagePackSerializer<T> Get<T>( SerializationContext context )
{
if ( context == null )
{
throw new ArgumentNullException( "context" );
}

Contract.Ensures( Contract.Result<MessagePackSerializer<T>>() != null );

return context.GetSerializer<T>();
}

/// <summary>
/// Gets a <see cref="IMessagePackSerializer"/> instance stored in <see cref="SerializationContext.Default"/>.
/// If a serializer for <paramref name="targetType"/> is not stored, <see cref="Create(Type)"/> will be called automatically.
/// </summary>
/// <param name="targetType">Target type.</param>
/// <returns>
/// A new <see cref="IMessagePackSerializer"/> instance to serialize/deserialize the object tree which the top is <paramref name="targetType"/> type.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="targetType"/> is <c>null</c>.
/// </exception>
/// <remarks>
/// To avoid boxing and strongly typed API is prefered, use <see cref="Get{T}()"/> instead when possible.
/// </remarks>
public static IMessagePackSerializer Get( Type targetType )
{
Contract.Ensures( Contract.Result<IMessagePackSerializer>() != null );

return Get( targetType, SerializationContext.Default );
}

/// <summary>
/// Gets a <see cref="IMessagePackSerializer"/> instance stored in the specified <see cref="SerializationContext"/>.
/// If a serializer for <paramref name="targetType"/> is not stored, <see cref="Create(Type,SerializationContext)"/> will be called automatically.
/// </summary>
/// <param name="targetType">Target type.</param>
/// <param name="context">
/// <see cref="SerializationContext"/> to store known/created serializers.
/// </param>
/// <returns>
/// A new <see cref="IMessagePackSerializer"/> instance to serialize/deserialize the object tree which the top is <paramref name="targetType"/> type.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="targetType"/> is <c>null</c>.
/// Or, <paramref name="context"/> is <c>null</c>.
/// </exception>
/// <remarks>
/// To avoid boxing and strongly typed API is prefered, use <see cref="Get{T}(SerializationContext)"/> instead when possible.
/// </remarks>
public static IMessagePackSerializer Get( Type targetType, SerializationContext context )
{
if ( targetType == null )
{
throw new ArgumentNullException( "targetType" );
}

if ( context == null )
{
throw new ArgumentNullException( "context" );
}

Contract.Ensures( Contract.Result<IMessagePackSerializer>() != null );

return context.GetSerializer( targetType );
}
}
}
@@ -0,0 +1,30 @@
#region -- License Terms --
//
// MessagePack for CLI
//
// Copyright (C) 2010 FUJIWARA, Yusuke
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion -- License Terms --

using System;
using System.Reflection;

namespace MsgPack.Serialization.Metadata
{
internal static class _MessagePackSerializer
{
public static readonly MethodInfo Create1_Method = typeof( MessagePackSerializer ).GetMethod( "Create", new[] { typeof( SerializationContext ) } );
}
}
@@ -24,14 +24,12 @@
#endif
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Threading;
#if NETFX_CORE
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
#endif
#if SILVERLIGHT
using System.Threading;
#endif

namespace MsgPack.Serialization
{
@@ -41,7 +39,7 @@ namespace MsgPack.Serialization
/// </summary>
public sealed class SerializationContext
{
private static readonly SerializationContext _default = new SerializationContext();
private static SerializationContext _default = new SerializationContext();

/// <summary>
/// Gets the default instance.
@@ -54,6 +52,14 @@ public static SerializationContext Default
get { return _default; }
}

/// <summary>
/// Resets the <see cref="Default"/> instance to brand new object.
/// </summary>
internal static void ResetDefault()
{
Interlocked.Exchange( ref _default, new SerializationContext() );
}

private readonly SerializerRepository _serializers;
#if SILVERLIGHT
private readonly object _typeLock;

0 comments on commit 8c8b4d7

Please sign in to comment.
You can’t perform that action at this time.