DynamicObjectTypeFallbackResolver makes public accessibility

This commit is contained in:
neuecc 2017-06-22 19:58:11 +09:00
Родитель abec6394ea
Коммит 4b7cfcc4be
5 изменённых файлов: 134 добавлений и 133 удалений

Просмотреть файл

@ -0,0 +1,84 @@
using MessagePack.Resolvers;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace MessagePack.Formatters
{
/// <summary>
/// PrimitiveObjectFormatter -> DynamicContractlessFormatter(NonGeneric).
/// </summary>
public class DynamicObjectTypeFallbackFormatter : IMessagePackFormatter<object>
{
delegate int SerializeMethod(object dynamicContractlessFormatter, ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver);
public static readonly IMessagePackFormatter<object> Instance = new DynamicObjectTypeFallbackFormatter();
static readonly System.Collections.Generic.Dictionary<Type, KeyValuePair<object, SerializeMethod>> serializers = new Dictionary<Type, KeyValuePair<object, SerializeMethod>>();
DynamicObjectTypeFallbackFormatter()
{
}
public int Serialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver)
{
if (value == null)
{
return MessagePackBinary.WriteNil(ref bytes, offset);
}
var type = value.GetType();
var ti = type.GetTypeInfo();
if (PrimitiveObjectFormatter.IsSupportedType(type, ti, value))
{
return PrimitiveObjectFormatter.Instance.Serialize(ref bytes, offset, value, formatterResolver);
}
KeyValuePair<object, SerializeMethod> formatterAndDelegate;
lock (serializers)
{
if (!serializers.TryGetValue(type, out formatterAndDelegate))
{
var formatter = DynamicContractlessObjectResolver.Instance.GetFormatterDynamic(type);
if (formatter == null)
{
throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + typeof(DynamicContractlessObjectResolver).Name);
}
var formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(type);
var param0 = Expression.Parameter(typeof(object), "formatter");
var param1 = Expression.Parameter(typeof(byte[]).MakeByRefType(), "bytes");
var param2 = Expression.Parameter(typeof(int), "offset");
var param3 = Expression.Parameter(typeof(object), "value");
var param4 = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");
var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(byte[]).MakeByRefType(), typeof(int), type, typeof(IFormatterResolver) });
var body = Expression.Call(
Expression.Convert(param0, formatterType),
serializeMethodInfo,
param1,
param2,
ti.IsValueType ? Expression.Unbox(param3, type) : Expression.Convert(param3, type),
param4);
var lambda = Expression.Lambda<SerializeMethod>(body, param0, param1, param2, param3, param4).Compile();
formatterAndDelegate = new KeyValuePair<object, SerializeMethod>(formatter, lambda);
serializers[type] = formatterAndDelegate;
}
}
return formatterAndDelegate.Value(formatterAndDelegate.Key, ref bytes, offset, value, formatterResolver);
}
public object Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
{
return PrimitiveObjectFormatter.Instance.Deserialize(bytes, offset, formatterResolver, out readSize);
}
}
}

Просмотреть файл

@ -28,4 +28,34 @@ namespace MessagePack.Resolvers
}
}
}
/// <summary>
/// In `object`, when serializing resolve by concrete type and when deserializing use primitive.
/// </summary>
public class DynamicObjectTypeFallbackResolver : IFormatterResolver
{
public static IFormatterResolver Instance = new DynamicObjectTypeFallbackResolver();
DynamicObjectTypeFallbackResolver()
{
}
public IMessagePackFormatter<T> GetFormatter<T>()
{
return FormatterCache<T>.formatter;
}
static class FormatterCache<T>
{
public static readonly IMessagePackFormatter<T> formatter;
static FormatterCache()
{
formatter = (typeof(T) == typeof(object))
? (IMessagePackFormatter<T>)(object)DynamicObjectTypeFallbackFormatter.Instance
: null;
}
}
}
}

Просмотреть файл

@ -1,11 +1,4 @@
using MessagePack.Formatters;
using System.Linq;
using MessagePack.Internal;
using System;
using System.Reflection;
using System.Collections.Generic;
using MessagePack.Resolvers;
using System.Linq.Expressions;
namespace MessagePack.Resolvers
{
@ -91,7 +84,7 @@ namespace MessagePack.Resolvers
DynamicContractlessObjectResolver.Instance,
// finally, try primitive -> dynamic contractless
DynamicObjectFallbackResolver.Instance
DynamicObjectTypeFallbackResolver.Instance
};
ContractlessStandardResolver()
@ -121,110 +114,4 @@ namespace MessagePack.Resolvers
}
}
}
}
namespace MessagePack.Internal
{
/// <summary>
/// In `object`, when serializing resolve by concrete type and when deserializing use primitive.
/// </summary>
internal class DynamicObjectFallbackResolver : IFormatterResolver
{
public static IFormatterResolver Instance = new DynamicObjectFallbackResolver();
DynamicObjectFallbackResolver()
{
}
public IMessagePackFormatter<T> GetFormatter<T>()
{
return FormatterCache<T>.formatter;
}
static class FormatterCache<T>
{
public static readonly IMessagePackFormatter<T> formatter;
static FormatterCache()
{
formatter = (typeof(T) == typeof(object))
? (IMessagePackFormatter<T>)(object)DynamicObjectFallbackResolverFormatter.Instance
: null;
}
}
}
internal class DynamicObjectFallbackResolverFormatter : IMessagePackFormatter<object>
{
internal delegate int SerializeMethod(object dynamicContractlessFormatter, ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver);
internal static readonly IMessagePackFormatter<object> Instance = new DynamicObjectFallbackResolverFormatter();
static readonly System.Collections.Generic.Dictionary<Type, KeyValuePair<object, SerializeMethod>> serializers = new Dictionary<Type, KeyValuePair<object, SerializeMethod>>();
DynamicObjectFallbackResolverFormatter()
{
}
public int Serialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver)
{
if (value == null)
{
return MessagePackBinary.WriteNil(ref bytes, offset);
}
var type = value.GetType();
var ti = type.GetTypeInfo();
if (PrimitiveObjectFormatter.IsSupportedType(type, ti, value))
{
return PrimitiveObjectFormatter.Instance.Serialize(ref bytes, offset, value, formatterResolver);
}
KeyValuePair<object, SerializeMethod> formatterAndDelegate;
lock (serializers)
{
if (!serializers.TryGetValue(type, out formatterAndDelegate))
{
var formatter = DynamicContractlessObjectResolver.Instance.GetFormatterDynamic(type);
if (formatter == null)
{
throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolver:" + typeof(DynamicContractlessObjectResolver).Name);
}
var formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(type);
var param0 = Expression.Parameter(typeof(object), "formatter");
var param1 = Expression.Parameter(typeof(byte[]).MakeByRefType(), "bytes");
var param2 = Expression.Parameter(typeof(int), "offset");
var param3 = Expression.Parameter(typeof(object), "value");
var param4 = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver");
var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(byte[]).MakeByRefType(), typeof(int), type, typeof(IFormatterResolver) });
var body = Expression.Call(
Expression.Convert(param0, formatterType),
serializeMethodInfo,
param1,
param2,
ti.IsValueType ? Expression.Unbox(param3, type) : Expression.Convert(param3, type),
param4);
var lambda = Expression.Lambda<SerializeMethod>(body, param0, param1, param2, param3, param4).Compile();
formatterAndDelegate = new KeyValuePair<object, SerializeMethod>(formatter, lambda);
serializers[type] = formatterAndDelegate;
}
}
return formatterAndDelegate.Value(formatterAndDelegate.Key, ref bytes, offset, value, formatterResolver);
}
public object Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
{
return PrimitiveObjectFormatter.Instance.Deserialize(bytes, offset, formatterResolver, out readSize);
}
}
}

Просмотреть файл

@ -25,27 +25,27 @@ namespace MessagePack.Tests
[Fact]
public void SimpleTest()
{
var p = new Person
{
Name = "John",
Addresses = new[]
var p = new Person
{
new Address { Street = "St." },
new Address { Street = "Ave." }
}
};
Name = "John",
Addresses = new[]
{
new Address { Street = "St." },
new Address { Street = "Ave." }
}
};
var result = MessagePack.MessagePackSerializer.Serialize(p, MessagePack.Resolvers.ContractlessStandardResolver.Instance);
var result = MessagePack.MessagePackSerializer.Serialize(p, MessagePack.Resolvers.ContractlessStandardResolver.Instance);
MessagePackSerializer.ToJson(result).Is(@"{""Name"":""John"",""Addresses"":[{""Street"":""St.""},{""Street"":""Ave.""}]}");
MessagePackSerializer.ToJson(result).Is(@"{""Name"":""John"",""Addresses"":[{""Street"":""St.""},{""Street"":""Ave.""}]}");
var p2 = MessagePack.MessagePackSerializer.Deserialize<Person>(result, MessagePack.Resolvers.ContractlessStandardResolver.Instance);
p2.Name.Is("John");
var addresses = p2.Addresses as IList;
var d1 = addresses[0] as IDictionary;
var d2 = addresses[1] as IDictionary;
(d1["Street"] as string).Is("St.");
(d2["Street"] as string).Is("Ave.");
var p2 = MessagePack.MessagePackSerializer.Deserialize<Person>(result, MessagePack.Resolvers.ContractlessStandardResolver.Instance);
p2.Name.Is("John");
var addresses = p2.Addresses as IList;
var d1 = addresses[0] as IDictionary;
var d2 = addresses[1] as IDictionary;
(d1["Street"] as string).Is("St.");
(d2["Street"] as string).Is("Ave.");
}
}
}

Просмотреть файл

@ -30,7 +30,7 @@ namespace MessagePack.Tests.ExtensionTests
return MessagePackSerializer.Deserialize<T>(MessagePackSerializer.Serialize(value, resolver), resolver);
}
[Fact]
[Fact(Skip ="assembly reference")]
public void ViewModelTest()
{
var vm = new ViewModel(10, 20, 30);
@ -52,7 +52,7 @@ namespace MessagePack.Tests.ExtensionTests
data.Is("[[3,-1,10],[3,-1,20],[3,-1,30]]");
}
[Fact]
[Fact(Skip = "assembly reference")]
public void MiscTest()
{
var rxCol = new ReactiveCollection<int> { 1, 10, 100 };