typeless - fix compiler error on Unity

This commit is contained in:
neuecc 2017-06-27 15:56:34 +09:00
Родитель 411318f91c
Коммит 9dd83054c5
8 изменённых файлов: 58 добавлений и 17 удалений

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

@ -202,6 +202,8 @@ var bin2 = MessagePackSerializer.Serialize(data);
ContractlessStandardResolver can serialize anonymous type, too.
I don't need type, I want to use like BinaryFormatter! You can use as typeless resolver and helpers. Please see [Typeless](https://github.com/neuecc/MessagePack-CSharp#typeless) section.
Resolver is key customize point of MessagePack for C#. Details, please see [extension point](https://github.com/neuecc/MessagePack-CSharp#extension-pointiformatterresolver).
Serialize ImmutableObject(SerializationConstructor)
@ -411,6 +413,33 @@ Console.WriteLine(dynamicModel["Items"][2]); // 100
So you can access indexer for msgpack map and array.
Typeless
---
Typeless API is like `BinaryFormatter`, embed type information to binary so no needs type to deserialize.
```csharp
object mc = new Sandbox.MyClass()
{
Age = 10,
FirstName = "hoge",
LastName = "huga"
};
// serialize to typeless
var bin = MessagePackSerializer.Typeless.Serialize(mc);
// binary data is embeded type-assembly information.
// ["Sandbox.MyClass, Sandbox",10,"hoge","huga"]
Console.WriteLine(MessagePackSerializer.ToJson(bin));
// can deserialize to MyClass with typeless
var objModel = MessagePackSerializer.Typeless.Deserialize(bin) as MyClass;
```
Type information is serialized by mspgack `ext` format, typecode is 100.
`MessagePackSerializer.Typeless` is shortcut of `Serialize/Deserialize<object>(TypelessContractlessStandardResolver.Instance)`. If you want to configure default typeless resolver, you can set by `MessagePackSerializer.Typeless.RegisterDefaultResolver`.
Performance
---
Benchmarks comparing to other serializers run on `Windows 10 Pro x64 Intel Core i7-6700K 4.00GHz, 32GB RAM`. Benchmark code is [here](https://github.com/neuecc/ZeroFormatter/tree/master/sandbox/PerformanceComparison) - and there [version info](https://github.com/neuecc/ZeroFormatter/blob/bc63cb925d/sandbox/PerformanceComparison/packages.config), ZeroFormatter and [FlatBuffers](https://google.github.io/flatbuffers/) has infinitely fast deserializer so ignore deserialize performance.
@ -698,7 +727,7 @@ Extension Point(IFormatterResolver)
| Resovler Name | Description |
| --- | --- |
| BuiltinResolver | Builtin primitive and standard classes resolver. It includes primitive(int, bool, string...) and there nullable, array and list. and some extra builtin types(Guid, Uri, BigInteger, etc...). |
| StandardResolver | Composited resolver . It resolves in the following order `builtin -> attribute -> dynamic enum -> dynamic generic -> dynamic union -> dynamic object -> primitive object`. This is the default of MessagePackSerializer. |
| StandardResolver | Composited resolver. It resolves in the following order `builtin -> attribute -> dynamic enum -> dynamic generic -> dynamic union -> dynamic object -> primitive object`. This is the default of MessagePackSerializer. |
| ContractlessStandardResolver | Composited `StandardResolver`(except primitive) -> `DynamicContractlessObjectResolver` -> `DynamicObjectTypeFallbackResolver`. It enables contractless serialization. |
| PrimitiveObjectResolver | MessagePack primitive object resolver. It is used fallback in `object` type and supports `bool`, `char`, `sbyte`, `byte`, `short`, `int`, `long`, `ushort`, `uint`, `ulong`, `float`, `double`, `DateTime`, `string`, `byte[]`, `ICollection`, `IDictionary`. |
| DynamicObjectTypeFallbackResolver | It is used fallback in `object` type and resolve primitive object -> dynamic contractless object |
@ -712,6 +741,8 @@ Extension Point(IFormatterResolver)
| DynamicUnionResolver | Resolver of interface marked by UnionAttribute. It uses dynamic code generation to create dynamic formatter. |
| DynamicObjectResolver | Resolver of class and struct maked by MessagePackObjectAttribute. It uses dynamic code generation to create dynamic formatter. |
| DynamicContractlessObjectResolver | Resolver of all classes and structs. It does not needs MessagePackObjectAttribute and serialized key as string(same as marked [MessagePackObject(true)]). |
| TypelessObjectResolver | Used for `object`, embed .NET type in binary by `ext(100)` format so no need to pass type in deserilization. |
| TypelessContractlessStandardResolver | Composited resolver. It resolves in the following order `nativedatetime -> builtin -> attribute -> dynamic enum -> dynamic generic -> dynamic union -> dynamic object -> dynamiccontractless -> typeless`. This is the default of `MessagePackSerializer.Typeless` |
It is the only configuration point to assemble the resolver's priority. In most cases, it is sufficient to have one custom resolver globally. CompositeResolver will be its helper.

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

@ -259,22 +259,23 @@ namespace Sandbox
class Program
{
static void Main(string[] args)
{
var mc = new MyClass()
{
object mc = new Sandbox.MyClass()
{
Age = 10,
FirstName = "hoge",
LastName = "huga"
};
var dict = new ConcurrentDictionary<int, MyClass>();
dict.TryAdd(1, mc);
var t = MessagePackSerializer.Typeless.Serialize(mc);
// serialize to typeless
var bin = MessagePackSerializer.Typeless.Serialize(mc);
// binary data is embeded type-assembly information.
// ["Sandbox.MyClass, Sandbox",10,"hoge","huga"]
Console.WriteLine(MessagePackSerializer.ToJson(bin));
var hoge = MessagePackSerializer.ToJson(t);
Console.WriteLine(hoge);
var nt = MessagePackSerializer.Typeless.Deserialize(t);
// can deserialize to MyClass with typeless
var objModel = MessagePackSerializer.Typeless.Deserialize(bin) as MyClass;

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

@ -115,6 +115,7 @@
<DesignTime>True</DesignTime>
<DependentUpon>TupleFormatter.tt</DependentUpon>
</Compile>
<Compile Include="Assets\Scripts\MessagePack\Formatters\TypelessFormatter.cs" />
<Compile Include="Assets\Scripts\MessagePack\Formatters\ValueTupleFormatter.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@ -155,6 +156,8 @@
<Compile Include="Assets\Scripts\MessagePack\Resolvers\OldSpecResolver.cs" />
<Compile Include="Assets\Scripts\MessagePack\Resolvers\PrimitiveObjectResolver.cs" />
<Compile Include="Assets\Scripts\MessagePack\Resolvers\StandardResolver.cs" />
<Compile Include="Assets\Scripts\MessagePack\Resolvers\TypelessContractlessStandardResolver.cs" />
<Compile Include="Assets\Scripts\MessagePack\Resolvers\TypelessObjectResolver.cs" />
<Compile Include="Assets\Scripts\MessagePack\Shims\Reflection.cs" />
<Compile Include="Assets\Scripts\MessagePack\StringEncoding.cs" />
<Compile Include="Assets\Scripts\MessagePack\Unity\Formatters.cs" />

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

@ -15,6 +15,8 @@ namespace MessagePack.Formatters
/// </summary>
public class TypelessFormatter : IMessagePackFormatter<object>
{
public const sbyte ExtensionTypeCode = 100;
static readonly Regex SubtractFullNameRegex = new Regex(@", Version=\d+.\d+.\d+.\d+, Culture=\w+, PublicKeyToken=\w+", RegexOptions.Compiled);
delegate int SerializeMethod(object dynamicContractlessFormatter, ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver);
@ -144,7 +146,7 @@ namespace MessagePack.Formatters
offset += 6; // mark will be written at the end, when size is known
offset += MessagePackBinary.WriteString(ref bytes, offset, typeName);
offset += formatterAndDelegate.Value(formatterAndDelegate.Key, ref bytes, offset, value, formatterResolver);
MessagePackBinary.WriteExtensionFormatHeaderForceExt32Block(ref bytes, startOffset, (sbyte)ReservedMessagePackExtensionTypeCode.DynamicObjectWithTypeName, offset - startOffset - 6);
MessagePackBinary.WriteExtensionFormatHeaderForceExt32Block(ref bytes, startOffset, (sbyte)TypelessFormatter.ExtensionTypeCode, offset - startOffset - 6);
return offset - startOffset;
}
@ -163,7 +165,7 @@ namespace MessagePack.Formatters
case MessagePackType.Extension:
{
var ext = MessagePackBinary.ReadExtensionFormatHeader(bytes, offset, out readSize);
if (ext.TypeCode == ReservedMessagePackExtensionTypeCode.DynamicObjectWithTypeName)
if (ext.TypeCode == TypelessFormatter.ExtensionTypeCode)
{
// it has type name serialized
offset += readSize;

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

@ -18,6 +18,8 @@ namespace MessagePack.Internal
return type.IsPublic;
}
#if NETSTANDARD1_4
public static bool IsAnonymous(this System.Reflection.TypeInfo type)
{
return type.GetCustomAttribute<CompilerGeneratedAttribute>() != null
@ -26,8 +28,6 @@ namespace MessagePack.Internal
&& (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}
#if NETSTANDARD1_4
public static bool IsConstructedGenericType(this System.Reflection.TypeInfo type)
{
return type.AsType().IsConstructedGenericType;

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

@ -1,4 +1,5 @@
using MessagePack.Internal;
using MessagePack.Formatters;
using MessagePack.Internal;
using MessagePack.LZ4;
using System;
using System.Globalization;
@ -165,7 +166,8 @@ namespace MessagePack
builder.Append(dt.ToString("o", CultureInfo.InvariantCulture));
builder.Append("\"");
}
else if (extHeader.TypeCode == ReservedMessagePackExtensionTypeCode.DynamicObjectWithTypeName)
#if NETSTANDARD1_4
else if (extHeader.TypeCode == TypelessFormatter.ExtensionTypeCode)
{
int startOffset = offset;
// prepare type name token
@ -196,6 +198,7 @@ namespace MessagePack
}
readSize = offset - startOffset;
}
#endif
else
{
var ext = MessagePackBinary.ReadExtensionFormat(bytes, offset, out readSize);

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

@ -184,7 +184,6 @@ namespace MessagePack
public static class ReservedMessagePackExtensionTypeCode
{
public const sbyte DateTime = -1;
public const sbyte DynamicObjectWithTypeName = 100;
}
public static class MessagePackRange

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

@ -239,7 +239,8 @@ namespace MessagePack
builder.Append(dt.ToString("o", CultureInfo.InvariantCulture));
builder.Append("\"");
}
else if (extHeader.TypeCode == ReservedMessagePackExtensionTypeCode.DynamicObjectWithTypeName)
#if NETSTANDARD1_4
else if (extHeader.TypeCode == TypelessFormatter.ExtensionTypeCode)
{
int startOffset = offset;
// prepare type name token
@ -270,6 +271,7 @@ namespace MessagePack
}
readSize = offset - startOffset;
}
#endif
else
{
var ext = MessagePackBinary.ReadExtensionFormat(bytes, offset, out readSize);