DynamicObjectTypeFallbackResolver makes public accessibility
This commit is contained in:
Родитель
abec6394ea
Коммит
4b7cfcc4be
|
@ -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 };
|
||||
|
|
Загрузка…
Ссылка в новой задаче