Merged all docs back into README
With exception of the build instructions, which I link to but keep in the CONTRIBUTING.md doc, which is the github standard location.
This commit is contained in:
Родитель
32cdc42a9d
Коммит
260c05b32c
|
@ -2,12 +2,7 @@
|
|||
|
||||
## How to Build
|
||||
|
||||
Open `MessagePack.sln` on Visual Studio 2017.
|
||||
Open `MessagePack.sln` on Visual Studio 2019.
|
||||
|
||||
Unity project uses symbolic links. See [making symlinks work in Git for Windows](https://stackoverflow.com/a/42137273/46926),
|
||||
or simply run this command before cloning:
|
||||
|
||||
git config --global core.symlinks true
|
||||
|
||||
Unity Project is using symbolic link. At first, run `make_unity_symlink.bat` under `src\MessagePack.UnityClient`.
|
||||
Unity Project requires several dependency DLL's. At first, run `link_assets.bat` under `src\MessagePack.UnityClient`.
|
||||
Then open that directory in the Unity Editor.
|
||||
|
|
1228
README.md
1228
README.md
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,18 +0,0 @@
|
|||
# Analyzer
|
||||
|
||||
The MessagePackAnalyzer helps to:
|
||||
|
||||
1. Automate defining your serializable objects.
|
||||
1. Produces compiler warnings due to incorrect attribute use, accessibility, and more.
|
||||
|
||||
![analyzergif](https://cloud.githubusercontent.com/assets/46207/23837445/ce734eae-07cb-11e7-9758-d69f0f095bc1.gif)
|
||||
|
||||
If you want to allow a specific type (for example, when registering a custom type), put `MessagePackAnalyzer.json` at the project root and make the Build Action to `AdditionalFiles`.
|
||||
|
||||
![image](https://cloud.githubusercontent.com/assets/46207/23837427/8a8d507c-07cb-11e7-9277-5a566eb0bfde.png)
|
||||
|
||||
This is a sample of the contents of `MessagePackAnalyzer.json`:
|
||||
|
||||
```json
|
||||
[ "MyNamespace.FooClass", "MyNameSpace.BarStruct" ]
|
||||
```
|
54
doc/aot.md
54
doc/aot.md
|
@ -1,54 +0,0 @@
|
|||
# AOT Code Generation (to support Unity/Xamarin)
|
||||
|
||||
By default, MessagePack for C# serializes custom objects by using [generating IL](https://msdn.microsoft.com/en-us/library/system.reflection.emit.ilgenerator.aspx) at runtime for custom, highly tuned formatters for each type. This code generation has a minor upfront perf cost.
|
||||
Because strict-AOT environments such as Xamarin and Unity IL2CPP forbid runtime code generation, MessagePack provides a way for you to run a code generator ahead of time as well.
|
||||
|
||||
> Note: When Unity targets the PC it allows dynamic code generation, so AOT is not required.
|
||||
|
||||
If you want to avoid the upfront dynamic generation cost or you need to run on Xamarin or Unity, you need AOT code generation. `mpc.exe`(MessagePackCompiler) is the code generator of MessagePack for C#. You can download mpc from the [releases](https://github.com/neuecc/MessagePack-CSharp/releases/) page, `mpc.zip`. mpc uses [Roslyn](https://github.com/dotnet/roslyn) to analyze source code.
|
||||
|
||||
```
|
||||
mpc arguments help:
|
||||
-i, --input [required]Input path of analyze csproj
|
||||
-o, --output [required]Output file path
|
||||
-c, --conditionalsymbol [optional, default=empty]conditional compiler symbol
|
||||
-r, --resolvername [optional, default=GeneratedResolver]Set resolver name
|
||||
-n, --namespace [optional, default=MessagePack]Set namespace root name
|
||||
-m, --usemapmode [optional, default=false]Force use map mode serialization
|
||||
```
|
||||
|
||||
```
|
||||
// Simple Sample:
|
||||
mpc.exe -i "..\src\Sandbox.Shared.csproj" -o "MessagePackGenerated.cs"
|
||||
|
||||
// Use force map simulate DynamicContractlessObjectResolver
|
||||
mpc.exe -i "..\src\Sandbox.Shared.csproj" -o "MessagePackGenerated.cs" -m
|
||||
```
|
||||
|
||||
If you create DLL by msbuild project, you can use Pre/Post build event.
|
||||
|
||||
```xml
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
mpc.exe, here is useful for analyze/generate target is self project.
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
mpc.exe, here is useful for analyze target is another project.
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
By default, `mpc.exe` generates resolver to `MessagePack.Resolvers.GeneratedResolver` and formatters generates to `MessagePack.Formatters.***`. You must specify this resolver each time you invoke the `MessagePackSerializer`.
|
||||
|
||||
```csharp
|
||||
// Do this once and store it for reuse.
|
||||
var resolver = MessagePack.Resolvers.CompositeResolver.CreateForAot(MessagePack.Resolvers.GeneratedResolver.Instance);
|
||||
var options = MessagePackSerializerOptions.Default.WithResolver(resolver);
|
||||
|
||||
// Each time you serialize/deserialize, specify the options:
|
||||
byte[] msgpackBytes = MessagePackSerializer.Serialize(myObject, options);
|
||||
T myObject2 = MessagePackSerializer.Deserialize<MyObject>(msgpackBytes, options);
|
||||
```
|
||||
|
||||
> Note: mpc.exe currently only supports running on Windows.
|
||||
You can run on [Mono](http://www.mono-project.com/), that supports Mac and Linux.
|
119
doc/api.md
119
doc/api.md
|
@ -1,119 +0,0 @@
|
|||
# API
|
||||
|
||||
## High-Level API (`MessagePackSerializer`)
|
||||
|
||||
The `MessagePackSerializer` class is the entry point of MessagePack for C#. Its static methods make up the main API of MessagePack for C#.
|
||||
|
||||
| API | Description |
|
||||
| --- | --- |
|
||||
| `Serialize<T>` | Serializes an object graph to msgpack binary. Async variety for Stream available. Non-generic overloads available. |
|
||||
| `Deserialize<T>` | Deserializes msgpack binary to an object graph. Async variety for Stream available. Non-generic overloads available. |
|
||||
| `SerializeToJson` | Serialize a MessagePack-compatible object graph to JSON instead of msgpack. Useful for debugging. |
|
||||
| `ConvertToJson` | Convert msgpack binary to JSON. Useful for debugging. |
|
||||
| `ConvertFromJson` | Convert JSON to msgpack binary. |
|
||||
|
||||
A `MessagePackSerializer.Typeless` class offers most of the same APIs as above, but removes all type arguments, forcing serialization to include the full type name of the root object. It uses the `TypelessContractlessStandardResolver`. Consider the result to be a .NET-specific msgpack binary.
|
||||
|
||||
MessagePack for C# fundamentally serializes with `IBufferWriter<byte>` level and deserializes with `ReadOnlySequence<byte>` or `Memory<byte>`. Method overloads are provided for conveniently working with common buffer types and the .NET `Stream` class, but some of these convenience overloads require copying a buffer once.
|
||||
|
||||
High-Level API uses memory pool internally to avoid unnecessary memory allocation. If result size is under 64K, allocates GC memory only for the return bytes.
|
||||
|
||||
Each serialize/deserialize method takes an optional `MessagePackSerializerOptions` parameter which can be used to specify a custom `IFormatterResolver` to use or to activate LZ4 compression support.
|
||||
|
||||
## Low-Level API (`IMessagePackFormatter<T>`)
|
||||
|
||||
The `IMessagePackFormatter<T>` interface is responsible for serializing a unique type. For example `Int32Formatter : IMessagePackFormatter<Int32>` represents Int32 MessagePack serializer.
|
||||
|
||||
```csharp
|
||||
public interface IMessagePackFormatter<T>
|
||||
{
|
||||
void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options);
|
||||
T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options);
|
||||
}
|
||||
```
|
||||
|
||||
Many built-in formatters exists under `MessagePack.Formatters`. Your custom types are usually automatically supported with the built-in type resolvers that generate new `IMessagePackFormatter<T>` types on-the-fly using dynamic code generation. See our [AOT code generation](aot.md) support for platforms that do not support this.
|
||||
|
||||
To take more control over the serialization of your custom types, write your own `IMessagePackFormatter<T>` implementation.
|
||||
Here is sample of write own formatter. Note its use of the primitive API that is described in the next section.
|
||||
|
||||
```csharp
|
||||
/// <summary>Serializes a <see cref="FileInfo" /> by its full path as a string.</summary>
|
||||
public class FileInfoFormatter<T> : IMessagePackFormatter<FileInfo>
|
||||
{
|
||||
public void Serialize(ref MessagePackWriter writer, FileInfo value, MessagePackSerializerOptions optionsr)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNil();
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteString(value.FullName);
|
||||
}
|
||||
|
||||
public FileInfo Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
|
||||
{
|
||||
if (reader.TryReadNil())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var path = reader.ReadString();
|
||||
return new FileInfo(path);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Your custom formatters must be discoverable via some `IFormatterResolver`. Learn more in our [resolvers](resolvers.md).
|
||||
|
||||
You can see many other samples from [builtin formatters](https://github.com/neuecc/MessagePack-CSharp/tree/master/src/MessagePack/Formatters).
|
||||
|
||||
## Primitive API (`MessagePackWriter`, `MessagePackReader`)
|
||||
|
||||
The `MessagePackWriter` and `MessagePackReader` structs make up the lowest-level API. They read and write the primitives types defined in the msgpack specification.
|
||||
|
||||
### `MessagePackReader`
|
||||
|
||||
A `MessagePackReader` can efficiently read from `ReadOnlyMemory<byte>` or `ReadOnlySequence<byte>` without any allocating
|
||||
except to allocate a new `string` as required by the `ReadString()` method. All other methods return either value structs
|
||||
or `ReadOnlySequence<byte>` slices for extensions/arrays.
|
||||
Reading directly from `ReadOnlySequence<byte>` means the reader can directly consume some modern high perforamnce APIs such as `PipeReader`.
|
||||
|
||||
| Method | Description |
|
||||
| --- | --- |
|
||||
| `Skip` | Advances the reader's position past the current value. If the value is complex (e.g. map, array) the entire structure is skipped. |
|
||||
| `Read*` | Read and return a value whose type is named by the method name from the current reader position. Throws if the expected type does not match the actual type. When reading numbers, the type need not match the binary-specified type exactly. The numeric value will be coerced into the desired type or throw if the integer type is too small for a large value. |
|
||||
| `TryReadNil` | Advances beyond the current value if the current value is `nil` and returns `true`; otherwise leaves the reader's position unchanged and returns `false`. |
|
||||
| `ReadBytes` | Returns a slice of the input sequence representing the contents of a `byte[]`, and advances the reader. |
|
||||
| `ReadStringSegment` | Returns a slice of the input sequence representing the contents of a `string` without decoding it, and advances the reader. |
|
||||
| `Clone` | Creates a new `MessagePackReader` with the specified input sequence and the same settings as the original reader. |
|
||||
| `CreatePeekReader` | Creates a new reader with the same position as this one, allowing the caller to "read ahead" without impacting the original reader's position. |
|
||||
| `NextCode` | Reads the low-level msgpack `byte` that describes the type of the next value. Does not advance the reader. See [msgpack format of first byte](https://github.com/msgpack/msgpack/blob/master/spec.md#overview). Its static class has `ToMessagePackType` and `ToFormatName` utility methods. `MessagePackRange` means Min-Max fix range of msgpack format. |
|
||||
| `NextMessagePackType` | Describes the `NextCode` value as a higher level category. Does not advance the reader. See [msgpack spec of source types](https://github.com/msgpack/msgpack/blob/master/spec.md#serialization-type-to-format-conversion). |
|
||||
| (others) | Other methods and properties as described by the .xml doc comment file and Intellisense. |
|
||||
|
||||
The `MessagePackReader` is capable of automatically interpreting both the old and new msgpack spec.
|
||||
|
||||
### `MessagePackWriter`
|
||||
|
||||
A `MessagePackWriter` writes to a given instance of `IBufferWriter<byte>`. Several common implementations of this exist, allowing zero allocations and minimal buffer copies while writing directly to several I/O APIs including `PipeWriter`.
|
||||
|
||||
The `MessagePackWriter` writes the new msgpack spec by default, but can write msgpack compatible with the old spec by setting the `OldSpec` property to `true`.
|
||||
|
||||
| Method | Description |
|
||||
| --- | --- |
|
||||
| `Clone` | Creates a new `MessagePackWriter` with the specified underlying `IBufferWriter<byte>` and the same settings as the original writer. |
|
||||
| `Flush` | Writes any buffered bytes to the underlying `IBufferWriter<byte>`. |
|
||||
| `WriteNil` | Writes the msgpack equivalent of .NET's `null` value. |
|
||||
| `Write` | Writes any msgpack primitive value in the most compact form possible. Has overloads for every primitive type defined by the msgpack spec. |
|
||||
| `Write*IntType*` | Writes an integer value in exactly the msgpack type specified, even if a more compact format exists. |
|
||||
| `WriteMapHeader` | Introduces a map by specifying the number of key=value pairs it contains. |
|
||||
| `WriteArrayHeader` | Introduces an array by specifying the number of elements it contains. |
|
||||
| `WriteExtensionFormat` | Writes the full content of an extension value including length, type code and content. |
|
||||
| `WriteExtensionFormatHeader` | Writes just the header (length and type code) of an extension value. |
|
||||
| `WriteRaw` | Copies the specified bytes directly to the underlying `IBufferWriter<byte>` without any validation. |
|
||||
| (others) | Other methods and properties as described by the .xml doc comment file and Intellisense. |
|
||||
|
||||
`DateTime` is serialized to [MessagePack Timestamp format](https://github.com/msgpack/msgpack/blob/master/spec.md#formats-timestamp), it serialize/deserialize UTC and loses `Kind` info and requires that `MessagePackWriter.OldSpec == false`.
|
||||
If you use the `NativeDateTimeResolver`, `DateTime` values will be serialized using .NET's native `Int64` represnetation, which preserves `Kind` info but may not be interoperable with non-.NET platforms.
|
|
@ -1,60 +0,0 @@
|
|||
# Compare with protobuf, JSON, ZeroFormatter
|
||||
|
||||
[protbuf-net](https://github.com/mgravell/protobuf-net) is major, most used binary-format library on .NET. I love protobuf-net and respect that great work. But if uses protobuf-net for general-purpose serialization format, you may encounts annoying issue.
|
||||
|
||||
```csharp
|
||||
[ProtoContract]
|
||||
public class Parent
|
||||
{
|
||||
[ProtoMember(1)]
|
||||
public int Primitive { get; set; }
|
||||
[ProtoMember(2)]
|
||||
public Child Prop { get; set; }
|
||||
[ProtoMember(3)]
|
||||
public int[] Array { get; set; }
|
||||
}
|
||||
|
||||
[ProtoContract]
|
||||
public class Child
|
||||
{
|
||||
[ProtoMember(1)]
|
||||
public int Number { get; set; }
|
||||
}
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
// serialize null.
|
||||
ProtoBuf.Serializer.Serialize<Parent>(ms, null);
|
||||
|
||||
ms.Position = 0;
|
||||
var result = ProtoBuf.Serializer.Deserialize<Parent>(ms);
|
||||
|
||||
Console.WriteLine(result != null); // True, not null. but all property are zero formatted.
|
||||
Console.WriteLine(result.Primitive); // 0
|
||||
Console.WriteLine(result.Prop); // null
|
||||
Console.WriteLine(result.Array); // null
|
||||
}
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
// serialize empty array.
|
||||
ProtoBuf.Serializer.Serialize<Parent>(ms, new Parent { Array = new int[0] });
|
||||
|
||||
ms.Position = 0;
|
||||
var result = ProtoBuf.Serializer.Deserialize<Parent>(ms);
|
||||
|
||||
Console.WriteLine(result.Array == null); // True, null!
|
||||
}
|
||||
```
|
||||
|
||||
protobuf(-net) can not handle null and empty collection correctly. Because protobuf has no `null` representation( [this](http://stackoverflow.com/questions/21631428/protobuf-net-deserializes-empty-collection-to-null-when-the-collection-is-a-prop) is the protobuf-net authors answer).
|
||||
|
||||
[MessagePack specification](https://github.com/msgpack/msgpack/blob/master/spec.md) can completely serialize C# type system. This is the reason to recommend MessagePack over protobuf.
|
||||
|
||||
Protocol Buffers has good IDL and [gRPC](http://www.grpc.io/), that is a much good point than MessagePack. If you want to use IDL, I recommend [Google.Protobuf](https://github.com/google/protobuf/tree/master/csharp/src/Google.Protobuf) than MessagePack.
|
||||
|
||||
JSON is good general-purpose format. It is perfect, simple and enough spec. [Utf8Json](https://github.com/neuecc/Utf8Json) which created me that adopts same architecture as MessagePack for C# and avoid encoding/decoing cost so work like binary. If you want to know about binary vs text, see [Utf8Json/which serializer should be used](https://github.com/neuecc/Utf8Json#which-serializer-should-be-used) section.
|
||||
|
||||
[ZeroFormatter](https://github.com/neuecc/ZeroFormatter/) is similar as [FlatBuffers](https://google.github.io/flatbuffers/) but specialized to C#. It is special. Deserialization is infinitely fast but instead the binary size is large. And ZeroFormatter's caching algorithm requires additional memory.
|
||||
|
||||
Again, ZeroFormatter is special. When situation matches with ZeroFormatter, it demonstrates power of format. But for many common uses, MessagePack for C# would be better.
|
|
@ -1,63 +0,0 @@
|
|||
# Extensions
|
||||
|
||||
MessagePack for C# has extension point and you can add external type's serialization support. There are official extension support.
|
||||
|
||||
```
|
||||
Install-Package MessagePack.ImmutableCollection
|
||||
Install-Package MessagePack.ReactiveProperty
|
||||
Install-Package MessagePack.UnityShims
|
||||
Install-Package MessagePack.AspNetCoreMvcFormatter
|
||||
```
|
||||
|
||||
`MessagePack.ImmutableCollection` package add support for [System.Collections.Immutable](https://www.nuget.org/packages/System.Collections.Immutable/) library. It adds `ImmutableArray<>`, `ImmutableList<>`, `ImmutableDictionary<,>`, `ImmutableHashSet<>`, `ImmutableSortedDictionary<,>`, `ImmutableSortedSet<>`, `ImmutableQueue<>`, `ImmutableStack<>`, `IImmutableList<>`, `IImmutableDictionary<,>`, `IImmutableQueue<>`, `IImmutableSet<>`, `IImmutableStack<>` serialization support.
|
||||
|
||||
`MessagePack.ReactiveProperty` package add support for [ReactiveProperty](https://github.com/runceel/ReactiveProperty) library. It adds `ReactiveProperty<>`, `IReactiveProperty<>`, `IReadOnlyReactiveProperty<>`, `ReactiveCollection<>`, `Unit` serialization support. It is useful for save viewmodel state.
|
||||
|
||||
`MessagePack.UnityShims` package provides shim of [Unity](https://unity3d.com/)'s standard struct(`Vector2`, `Vector3`, `Vector4`, `Quaternion`, `Color`, `Bounds`, `Rect`, `AnimationCurve`, `Keyframe`, `Matrix4x4`, `Gradient`, `Color32`, `RectOffset`, `LayerMask`, `Vector2Int`, `Vector3Int`, `RangeInt`, `RectInt`, `BoundsInt`) and their formatters. It can enable to communicate between server and Unity client.
|
||||
|
||||
After install, extension package must enable by configuration. Here is sample of enable all extension.
|
||||
|
||||
```csharp
|
||||
// set extensions to default resolver.
|
||||
MessagePack.Resolvers.CompositeResolver.RegisterAndSetAsDefault(
|
||||
// enable extension packages first
|
||||
ImmutableCollectionResolver.Instance,
|
||||
ReactivePropertyResolver.Instance,
|
||||
MessagePack.Unity.Extension.UnityBlitResolver.Instance,
|
||||
MessagePack.Unity.UnityResolver.Instance,
|
||||
|
||||
// finaly use standard(default) resolver
|
||||
StandardResolver.Instance);
|
||||
);
|
||||
```
|
||||
|
||||
Configuration details, see:[Extension Point section](https://github.com/neuecc/MessagePack-CSharp#extension-pointiformatterresolver).
|
||||
|
||||
`MessagePack.AspNetCoreMvcFormatter` is add-on of [ASP.NET Core MVC](https://github.com/aspnet/Mvc)'s serialization to boostup performance. This is configuration sample.
|
||||
|
||||
```csharp
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMvc().AddMvcOptions(option =>
|
||||
{
|
||||
option.OutputFormatters.Clear();
|
||||
option.OutputFormatters.Add(new MessagePackOutputFormatter(ContractlessStandardResolver.Instance));
|
||||
option.InputFormatters.Clear();
|
||||
option.InputFormatters.Add(new MessagePackInputFormatter(ContractlessStandardResolver.Instance));
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Author is creating other extension packages, too.
|
||||
|
||||
* [MasterMemory](https://github.com/neuecc/MasterMemory) - Embedded Readonly In-Memory Document Database
|
||||
* [MagicOnion](https://github.com/neuecc/MagicOnion) - gRPC based HTTP/2 RPC Streaming Framework
|
||||
* [DatadogSharp](https://github.com/neuecc/DatadogSharp) - C# Datadog client
|
||||
|
||||
You can make your own extension serializers or integrate with framework, let's create them and share it!
|
||||
|
||||
* [MessagePack.FSharpExtensions](https://github.com/pocketberserker/MessagePack.FSharpExtensions) - supports F# list,set,map,unit,option,discriminated union
|
||||
* [MessagePack.NodaTime](https://github.com/ARKlab/MessagePack) -
|
||||
Support for NodaTime types to MessagePack C#
|
||||
* [WebApiContrib.Core.Formatter.MessagePack](https://github.com/WebApiContrib/WebAPIContrib.Core#formatters) - supports ASP.NET Core MVC([details in blog post](https://www.strathweb.com/2017/06/using-messagepack-with-asp-net-core-mvc/))
|
||||
* [MessagePack.MediaTypeFormatter](https://github.com/sketch7/MessagePack.MediaTypeFormatter) - MessagePack MediaTypeFormatter
|
|
@ -1,90 +0,0 @@
|
|||
# Formatters
|
||||
|
||||
## Built-in support types
|
||||
|
||||
These types can serialize by default.
|
||||
|
||||
Primitives(`int`, `string`, etc...), `Enum`, `Nullable<>`, `TimeSpan`, `DateTime`, `DateTimeOffset`, `Nil`, `Guid`, `Uri`, `Version`, `StringBuilder`, `BitArray`, `ArraySegment<>`, `BigInteger`, `Complext`, `Task`, `Array[]`, `Array[,]`, `Array[,,]`, `Array[,,,]`, `KeyValuePair<,>`, `Tuple<,...>`, `ValueTuple<,...>`, `List<>`, `LinkedList<>`, `Queue<>`, `Stack<>`, `HashSet<>`, `ReadOnlyCollection<>`, `IList<>`, `ICollection<>`, `IEnumerable<>`, `Dictionary<,>`, `IDictionary<,>`, `SortedDictionary<,>`, `SortedList<,>`, `ILookup<,>`, `IGrouping<,>`, `ObservableCollection<>`, `ReadOnlyOnservableCollection<>`, `IReadOnlyList<>`, `IReadOnlyCollection<>`, `ISet<>`, `ConcurrentBag<>`, `ConcurrentQueue<>`, `ConcurrentStack<>`, `ReadOnlyDictionary<,>`, `IReadOnlyDictionary<,>`, `ConcurrentDictionary<,>`, `Lazy<>`, `Task<>`, custom inherited `ICollection<>` or `IDictionary<,>` with paramterless constructor, `IList`, `IDictionary` and custom inherited `ICollection` or `IDictionary` with paramterless constructor(includes `ArrayList` and `Hashtable`).
|
||||
|
||||
You can add custom type support and has some official/third-party extension package. for ImmutableCollections(`ImmutableList<>`, etc), for ReactiveProperty and for Unity(`Vector3`, `Quaternion`, etc...), for F#(Record, FsList, Discriminated Unions, etc...). Please see [extensions section](https://github.com/neuecc/MessagePack-CSharp#extensions).
|
||||
|
||||
`MessagePack.Nil` is built-in null/void/unit representation type of MessagePack for C#.
|
||||
|
||||
## MessagePackFormatterAttribute
|
||||
|
||||
MessagePackFormatterAttribute is lightweight extension point of class, struct, interface, enum and property/field. This is like JSON.NET's JsonConverterAttribute. For example, serialize private field, serialize x10 formatter.
|
||||
|
||||
```csharp
|
||||
[MessagePackFormatter(typeof(CustomObjectFormatter))]
|
||||
public class CustomObject
|
||||
{
|
||||
string internalId;
|
||||
|
||||
public CustomObject()
|
||||
{
|
||||
this.internalId = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
// serialize/deserialize internal field.
|
||||
class CustomObjectFormatter : IMessagePackFormatter<CustomObject>
|
||||
{
|
||||
public void Serialize(ref MessagePackWriter writer, CustomObject value, IFormatterResolver formatterResolver)
|
||||
{
|
||||
formatterResolver.GetFormatterWithVerify<string>().Serialize(ref writer, value.internalId, formatterResolver);
|
||||
}
|
||||
|
||||
public CustomObject Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
|
||||
{
|
||||
var id = formatterResolver.GetFormatterWithVerify<string>().Deserialize(ref reader, formatterResolver);
|
||||
return new CustomObject { internalId = id };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// per field, member
|
||||
|
||||
public class Int_x10Formatter : IMessagePackFormatter<int>
|
||||
{
|
||||
public int Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
|
||||
{
|
||||
return reader.ReadInt32() * 10;
|
||||
}
|
||||
|
||||
public void Serialize(ref MessagePackWriter writer, int value, IFormatterResolver formatterResolver)
|
||||
{
|
||||
writer.WriteInt32(value * 10);
|
||||
}
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class MyClass
|
||||
{
|
||||
// You can attach custom formatter per member.
|
||||
[Key(0)]
|
||||
[MessagePackFormatter(typeof(Int_x10Formatter))]
|
||||
public int MyProperty1 { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
Formatter is retrieved by `AttributeFormatterResolver`, it is included in `StandardResolver`.
|
||||
|
||||
## IgnoreFormatter
|
||||
|
||||
`IgnoreFormatter<T>` is lightweight extension point of class and struct, if exists can't serializable type in external type, you can register `IgnoreFormatter<T>` that serialize to nil.
|
||||
|
||||
```csharp
|
||||
// CompositeResolver can set custom formatter.
|
||||
MessagePack.Resolvers.CompositeResolver.RegisterAndSetAsDefault(
|
||||
new IMessagePackFormatter[]
|
||||
{
|
||||
// for example, register reflection infos(can not serialize in default)
|
||||
new IgnoreFormatter<MethodBase>(),
|
||||
new IgnoreFormatter<MethodInfo>(),
|
||||
new IgnoreFormatter<PropertyInfo>(),
|
||||
new IgnoreFormatter<FieldInfo>()
|
||||
},
|
||||
new IFormatterResolver[]
|
||||
{
|
||||
ContractlessStandardResolver.Instance
|
||||
});
|
||||
```
|
27
doc/index.md
27
doc/index.md
|
@ -1,27 +0,0 @@
|
|||
# MessagePack Documentation
|
||||
|
||||
Learn more about various aspects of MessagePack.
|
||||
|
||||
## Quick start
|
||||
|
||||
* Learn how to [install MessagePack](installation.md) for your project.
|
||||
* Check out our [quick start tutorial](quickstart.md).
|
||||
* Learn more about [serializing your own objects](serialization.md).
|
||||
* The [MessagePack analyzer for C#](analyzer.md) creates warnings and adds code fixes to make you more productive.
|
||||
|
||||
## Get more out of the library
|
||||
|
||||
* The [high and low level APIs](api.md) will help you find the write types and methods to optimally use.
|
||||
* Check out [packages that extend MessagePack](extension_packages.md) to make it a great fit for several technologies.
|
||||
* How to use MessagePack in your [RPC solution](rpc.md).
|
||||
* Learn about [built-in type support and using formatters to customize serialization](formatters.md).
|
||||
* [Custom resolvers](resolvers.md)
|
||||
* Compress your MessagePack data stream or file size using [built-in LZ4 support](lz4.md).
|
||||
* How the [msgpack spec's extension types are used](msgpack_extensiontypes.md) in this library and which this library reserves.
|
||||
* Learn about [using this library with Unity](unity.md).
|
||||
* The [ahead of Time (AOT) code generator](aot.md) allows you to take the highly tuned MessagePack serializer to platforms that do not allow dynamic code generation (e.g. Xamarin, Unity).
|
||||
|
||||
## Deciding between various MessagePack libraries?
|
||||
|
||||
* Check out how this library [compares to the competition](comparison.md).
|
||||
* How MessagePack achieves such [great performance](performance.md).
|
|
@ -1,24 +0,0 @@
|
|||
# Installation
|
||||
|
||||
This library is distributed via NuGet package and with special [support for Unity](doc/unity.md).
|
||||
|
||||
## NuGet packages
|
||||
|
||||
We target .NET Standard 2.0 with special optimizations for .NET Core 2.1+.
|
||||
|
||||
Install-Package MessagePack
|
||||
|
||||
Install the optional C# analyzer to get warnings for coding mistakes and code fixes to save you time:
|
||||
|
||||
Install-Package MessagePackAnalyzer
|
||||
|
||||
Extension Packages (learn more in our [extensions section](doc/extensions.md)):
|
||||
|
||||
Install-Package MessagePack.ImmutableCollection
|
||||
Install-Package MessagePack.ReactiveProperty
|
||||
Install-Package MessagePack.UnityShims
|
||||
Install-Package MessagePack.AspNetCoreMvcFormatter
|
||||
|
||||
## Unity
|
||||
|
||||
For Unity, download from [releases](https://github.com/neuecc/MessagePack-CSharp/releases) page, providing `.unitypackage`. Unity IL2CPP or Xamarin AOT Environment, check the [pre-code generation section](doc/aot.md).
|
35
doc/lz4.md
35
doc/lz4.md
|
@ -1,35 +0,0 @@
|
|||
# LZ4 Compression
|
||||
|
||||
MessagePack is a fast and *compact* format but it is not compression. [LZ4](https://github.com/lz4/lz4) is extremely fast compression algorithm, with MessagePack for C# can achive extremely fast perfrormance and extremely compact binary size!
|
||||
|
||||
MessagePack for C# has built-in LZ4 support. You can use `LZ4MessagePackSerializer` instead of `MessagePackSerializer`. Builtin support is special, I've created serialize-compression pipeline and special tuned for the pipeline so share the working memory, don't allocate, don't resize until finished.
|
||||
|
||||
Serialized binary is not simply compressed lz4 binary. Serialized binary is valid MessagePack binary used ext-format and custom typecode(99).
|
||||
|
||||
```csharp
|
||||
var array= Enumerable.Range(1, 100).Select(x => new MyClass { Age = 5, FirstName = "foo", LastName = "bar" }).ToArray();
|
||||
|
||||
// call LZ4MessagePackSerializer instead of MessagePackSerializer, api is completely same
|
||||
var lz4Bytes = LZ4MessagePackSerializer.Serialize(array);
|
||||
var mc2 = LZ4MessagePackSerializer.Deserialize<MyClass[]>(lz4Bytes);
|
||||
|
||||
// you can dump lz4 message pack
|
||||
// [[5,"hoge","huga"],[5,"hoge","huga"],....]
|
||||
var json = LZ4MessagePackSerializer.ToJson(lz4Bytes);
|
||||
Console.WriteLine(json);
|
||||
|
||||
// lz4Bytes is valid MessagePack, it is using ext-format( [TypeCode:99, SourceLength|CompressedBinary] )
|
||||
// [99,"0gAAA+vf3ABkkwWjZm9vo2JhcgoA////yVBvo2Jhcg=="]
|
||||
var rawJson = MessagePackSerializer.ToJson(lz4Bytes);
|
||||
Console.WriteLine(rawJson);
|
||||
```
|
||||
|
||||
built-in LZ4 support uses primitive LZ4 API. The LZ4 API is more efficient if you know the size of original source length. Therefore, size is written on the top.
|
||||
|
||||
> Compression speed is not always fast. Depending on the target binary, it may be short or longer. However, even at worst, it is about twice, but it is still often faster than other uncompressed serializers.
|
||||
|
||||
If target binary size under 64 bytes, LZ4MessagePackSerializer does not compress to optimize small size serialization.
|
||||
|
||||
### Attributions
|
||||
|
||||
lz4 compression support is using Milosz Krajewski's [lz4net](https://github.com/MiloszKrajewski/lz4net) code with some modified.
|
|
@ -1,19 +0,0 @@
|
|||
# Reserved Extension Types
|
||||
|
||||
MessagePack for C# already used some messagepack ext type codes, be careful to use same ext code.
|
||||
|
||||
| Code | Type | Use by |
|
||||
| --- | --- | --- |
|
||||
| -1 | DateTime | msgpack-spec reserved for timestamp |
|
||||
| 30 | Vector2[] | for Unity, UnsafeBlitFormatter |
|
||||
| 31 | Vector3[] | for Unity, UnsafeBlitFormatter |
|
||||
| 32 | Vector4[] | for Unity, UnsafeBlitFormatter |
|
||||
| 33 | Quaternion[] | for Unity, UnsafeBlitFormatter |
|
||||
| 34 | Color[] | for Unity, UnsafeBlitFormatter |
|
||||
| 35 | Bounds[] | for Unity, UnsafeBlitFormatter |
|
||||
| 36 | Rect[] | for Unity, UnsafeBlitFormatter |
|
||||
| 37 | Int[] | for Unity, UnsafeBlitFormatter |
|
||||
| 38 | Float[] | for Unity, UnsafeBlitFormatter |
|
||||
| 39 | Double[] | for Unity, UnsafeBlitFormatter |
|
||||
| 99 | All | LZ4MessagePackSerializer |
|
||||
| 100 | object | TypelessFormatter |
|
|
@ -1,81 +0,0 @@
|
|||
# MessagePack 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.
|
||||
|
||||
![image](https://cloud.githubusercontent.com/assets/46207/23835765/55fe494e-07b0-11e7-98be-5e7a9411da40.png)
|
||||
|
||||
MessagePack for C# uses many techniques for improve performance.
|
||||
|
||||
* Serializer uses only `IBufferWriter<byte>` rather than `System.IO.Stream` for reduced overhead.
|
||||
* Buffers are rented from pools to reduce allocations, keeping throughput high through reduced GC pressure.
|
||||
* Don't create intermediate utility instance(XxxWriter/Reader, XxxContext, etc...)
|
||||
* Utilize dynamic code generation to avoid boxing value types. Use AOT generation on platforms that prohibit JIT.
|
||||
* Getting cached generated formatter on static generic field (don't use dictinary-cache because dictionary lookup is overhead). See [Resolvers](https://github.com/neuecc/MessagePack-CSharp/tree/209f301e2e595ed366408624011ba2e856d23429/src/MessagePack/Resolvers)
|
||||
* Heavily tuned dynamic IL code generation to avoid boxing value types. See [DynamicObjectTypeBuilder](https://github.com/neuecc/MessagePack-CSharp/blob/209f301e2e595ed366408624011ba2e856d23429/src/MessagePack/Resolvers/DynamicObjectResolver.cs#L142-L754).
|
||||
Use AOT generation on platforms that prohibit JIT.
|
||||
* Call PrimitiveAPI directly when il code generation knows target is primitive
|
||||
* Reduce branch of variable length format when il code generation knows target(integer/string) range
|
||||
* Don't use `IEnumerable<T>` abstraction on iterate collection, [see:CollectionFormatterBase](https://github.com/neuecc/MessagePack-CSharp/blob/209f301e2e595ed366408624011ba2e856d23429/src/MessagePack/Formatters/CollectionFormatter.cs#L192-L355) and inherited collection formatters
|
||||
* Uses pre generated lookup table to reduce check messagepack type, [see: MessagePackBinary](https://github.com/neuecc/MessagePack-CSharp/blob/209f301e2e595ed366408624011ba2e856d23429/src/MessagePack/MessagePackBinary.cs#L15-L212)
|
||||
* Uses optimized type key dictionary for non-generic methods, [see: ThreadsafeTypeKeyHashTable](https://github.com/neuecc/MessagePack-CSharp/blob/91312921cb7fe987f48336768c898a76ac7dbb40/src/MessagePack/Internal/ThreadsafeTypeKeyHashTable.cs)
|
||||
* Avoid string key decode for lookup map(string key) key and uses automata based name lookup with il inlining code generation, see: [AutomataDictionary](https://github.com/neuecc/MessagePack-CSharp/blob/bcedbce3fd98cb294210d6b4a22bdc4c75ccd916/src/MessagePack/Internal/AutomataDictionary.cs)
|
||||
* For string key encode, pre-generated member name bytes and use fixed sized binary copy in IL, see: [UnsafeMemory.cs](https://github.com/neuecc/MessagePack-CSharp/blob/f17ddc5d107d3a2f66f60398b214ef87919ff892/src/MessagePack/Internal/UnsafeMemory.cs)
|
||||
|
||||
Before creating this library, I implemented a fast fast serializer with [ZeroFormatter#Performance](https://github.com/neuecc/ZeroFormatter#performance). And this is a further evolved implementation. MessagePack for C# is always fast, optimized for all types(primitive, small struct, large object, any collections).
|
||||
|
||||
Deserialize Performance per options
|
||||
---
|
||||
Performance varies depending on options. This is a micro benchamark with [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet). Target object has 9 members(`MyProperty1` ~ `MyProperty9`), value are zero.
|
||||
|
||||
| Method | Mean | Error | Scaled | Gen 0 | Allocated |
|
||||
|-------------------- |------------:|------:|-------:|-------:|----------:|
|
||||
| IntKey | 72.67 ns | NA | 1.00 | 0.0132 | 56 B |
|
||||
| StringKey | 217.95 ns | NA | 3.00 | 0.0131 | 56 B |
|
||||
| Typeless_IntKey | 176.71 ns | NA | 2.43 | 0.0131 | 56 B |
|
||||
| Typeless_StringKey | 378.64 ns | NA | 5.21 | 0.0129 | 56 B |
|
||||
| MsgPackCliMap | 1,355.26 ns | NA | 18.65 | 0.1431 | 608 B |
|
||||
| MsgPackCliArray | 455.28 ns | NA | 6.26 | 0.0415 | 176 B |
|
||||
| ProtobufNet | 265.85 ns | NA | 3.66 | 0.0319 | 136 B |
|
||||
| Hyperion | 366.47 ns | NA | 5.04 | 0.0949 | 400 B |
|
||||
| JsonNetString | 2,783.39 ns | NA | 38.30 | 0.6790 | 2864 B |
|
||||
| JsonNetStreamReader | 3,297.90 ns | NA | 45.38 | 1.4267 | 6000 B |
|
||||
| JilString | 553.65 ns | NA | 7.62 | 0.0362 | 152 B |
|
||||
| JilStreamReader | 1,408.46 ns | NA | 19.38 | 0.8450 | 3552 B |
|
||||
|
||||
IntKey, StringKey, Typeless_IntKey, Typeless_StringKey are MessagePack for C# options. All MessagePack for C# options achive zero memory allocation on deserialization process. JsonNetString/JilString is deserialized from string. JsonNetStreamReader/JilStreamReader is deserialized from UTF8 byte[] with StreamReader. Deserialization is normally read from Stream. Thus, it will be restored from byte[](or Stream) instead of string.
|
||||
|
||||
MessagePack for C# IntKey is fastest. StringKey is slower than IntKey because matching from the character string is required. If IntKey, read array length, for(array length) { binary decode }. If StringKey, read map length, for(map length) { decode key, lookup by key, binary decode } so requires additional two steps(decode key and lookup by key).
|
||||
|
||||
String key is often useful, contractless, simple replacement of JSON, interoperability with other languages, and more certain versioning. MessagePack for C# is also optimized for String Key. First of all, it do not decode UTF8 byte[] to String for matching with the member name, it will look up the byte[] as it is(avoid decode cost and extra allocation).
|
||||
|
||||
And It will try to match each `long type` (per 8 character, if it is not enough, pad with 0) using [automata](https://en.wikipedia.org/wiki/Automata_theory) and inline it when IL code generating.
|
||||
|
||||
![image](https://user-images.githubusercontent.com/46207/29754771-216b40e2-8bc7-11e7-8310-1c3602e80a08.png)
|
||||
|
||||
This also avoids calculating the hash code of byte[], and the comparison can be made several times on a long unit.
|
||||
|
||||
This is the sample decompile of generated deserializer code by [ILSpy](http://ilspy.net/).
|
||||
|
||||
![image](https://user-images.githubusercontent.com/46207/29754804-b5ba0f44-8bc7-11e7-9f6b-0c8f3c041237.png)
|
||||
|
||||
If the number of nodes is large, search with a embedded binary search.
|
||||
|
||||
Extra note, this is serialize benchmark result.
|
||||
|
||||
| Method | Mean | Error | Scaled | Gen 0 | Allocated |
|
||||
|-------------------- |------------:|------:|-------:|-------:|----------:|
|
||||
| IntKey | 84.11 ns | NA | 1.00 | 0.0094 | 40 B |
|
||||
| StringKey | 126.75 ns | NA | 1.51 | 0.0341 | 144 B |
|
||||
| Typeless_IntKey | 183.31 ns | NA | 2.18 | 0.0265 | 112 B |
|
||||
| Typeless_StringKey | 193.95 ns | NA | 2.31 | 0.0513 | 216 B |
|
||||
| MsgPackCliMap | 967.68 ns | NA | 11.51 | 0.1297 | 552 B |
|
||||
| MsgPackCliArray | 284.20 ns | NA | 3.38 | 0.1006 | 424 B |
|
||||
| ProtobufNet | 176.43 ns | NA | 2.10 | 0.0665 | 280 B |
|
||||
| Hyperion | 280.14 ns | NA | 3.33 | 0.1674 | 704 B |
|
||||
| ZeroFormatter | 149.95 ns | NA | 1.78 | 0.1009 | 424 B |
|
||||
| JsonNetString | 1,432.55 ns | NA | 17.03 | 0.4616 | 1944 B |
|
||||
| JsonNetStreamWriter | 1,775.72 ns | NA | 21.11 | 1.5526 | 6522 B |
|
||||
| JilString | 547.51 ns | NA | 6.51 | 0.3481 | 1464 B |
|
||||
| JilStreamWriter | 778.78 ns | NA | 9.26 | 1.4448 | 6066 B |
|
||||
|
||||
Of course, IntKey is fastest but StringKey also good.
|
|
@ -1,54 +0,0 @@
|
|||
# Quick Start
|
||||
|
||||
Define the class to be serialized and attribute the class with `[MessagePackObject]`.
|
||||
Attribute public members (property or field) with `[Key]`.
|
||||
|
||||
```csharp
|
||||
[MessagePackObject]
|
||||
public class MyClass
|
||||
{
|
||||
// Key is serialization index, it is important for versioning.
|
||||
[Key(0)]
|
||||
public int Age { get; set; }
|
||||
|
||||
[Key(1)]
|
||||
public string FirstName { get; set; }
|
||||
|
||||
[Key(2)]
|
||||
public string LastName { get; set; }
|
||||
|
||||
// public members and does not serialize target, mark IgnoreMemberttribute
|
||||
[IgnoreMember]
|
||||
public string FullName { get { return FirstName + LastName; } }
|
||||
}
|
||||
```
|
||||
|
||||
Call `MessagePackSerializer.Serialize<T>/Deserialize<T>` to serialize/deserialize your object graph.
|
||||
You can also use the `ConvertToJson` method to see a human readable representation of the msgpack that was written.
|
||||
|
||||
```csharp
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var mc = new MyClass
|
||||
{
|
||||
Age = 99,
|
||||
FirstName = "hoge",
|
||||
LastName = "huga",
|
||||
};
|
||||
|
||||
// call Serialize/Deserialize, that's all.
|
||||
byte[] bytes = MessagePackSerializer.Serialize(mc);
|
||||
MyClass mc2 = MessagePackSerializer.Deserialize<MyClass>(bytes);
|
||||
|
||||
// you can dump msgpack binary to human readable json.
|
||||
// In default, MeesagePack for C# reduce property name information.
|
||||
// [99,"hoge","huga"]
|
||||
var json = MessagePackSerializer.ConvertToJson(bytes);
|
||||
Console.WriteLine(json);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
By default the attribute is required. Optionally it can be unnecessary, see [Object Serialization section](serialization.md) and [Formatter Resolver section](resolvers.md) for details.
|
132
doc/resolvers.md
132
doc/resolvers.md
|
@ -1,132 +0,0 @@
|
|||
# Resolvers (`IFormatterResolver`)
|
||||
|
||||
An `IFormatterResolver` is storage of typed serializers. The `MessagePackSerializer` API accepts a `MessagePackSerializerOptions` object which specifies the `IFormatterResolver` to use, allowing customization of the serialization of complex types.
|
||||
|
||||
| Resolver 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 -> dynamic object fallback`. This is the default of MessagePackSerializer. |
|
||||
| ContractlessStandardResolver | Composited `StandardResolver`(except dynamic object fallback) -> `DynamicContractlessObjectResolver` -> `DynamicObjectTypeFallbackResolver`. It enables contractless serialization. |
|
||||
| StandardResolverAllowPrivate | Same as StandardResolver but allow serialize/deserialize private members. |
|
||||
| ContractlessStandardResolverAllowPrivate | Same as ContractlessStandardResolver but allow serialize/deserialize private members. |
|
||||
| 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 | Serialize is used type in from `object` type, deserialize is used PrimitiveObjectResolver. |
|
||||
| AttributeFormatterResolver | Get formatter from `[MessagePackFormatter]` attribute. |
|
||||
| CompositeResolver | Composes several resolvers and/or formatters together in an ordered list, allowing reuse and overriding of behaviors of existing resolvers and formatters. |
|
||||
| NativeDateTimeResolver | Serialize by .NET native DateTime binary format. |
|
||||
| UnsafeBinaryResolver | Guid and Decimal serialize by binary representation. It is faster than standard(string) representation. |
|
||||
| DynamicEnumResolver | Resolver of enum and there nullable, serialize there underlying type. It uses dynamic code generation to avoid boxing and boostup performance serialize there name. |
|
||||
| DynamicEnumAsStringResolver | Resolver of enum and there nullable. It uses reflection call for resolve nullable at first time. |
|
||||
| DynamicGenericResolver | Resolver of generic type(`Tuple<>`, `List<>`, `Dictionary<,>`, `Array`, etc). It uses reflection call for resolve generic argument at first time. |
|
||||
| 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)]). |
|
||||
| DynamicObjectResolverAllowPrivate | Same as DynamicObjectResolver but allow serialize/deserialize private members. |
|
||||
| DynamicContractlessObjectResolverAllowPrivate | Same as DynamicContractlessObjectResolver but allow serialize/deserialize private members. |
|
||||
| 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` |
|
||||
|
||||
Each invocation of `MessagePackSerializer` accepts only a single resolver. Most object graphs will need more than one for serialization, so composing a single resolver made up of several is often required, and can be done with the `CompositeResolver` as shown below:
|
||||
|
||||
```csharp
|
||||
// Do this once and store it for reuse.
|
||||
var resolver = new MessagePack.Resolvers.CompositeResolver();
|
||||
resolver.RegisterResolver(
|
||||
// resolver custom types first
|
||||
ImmutableCollectionResolver.Instance,
|
||||
ReactivePropertyResolver.Instance,
|
||||
MessagePack.Unity.Extension.UnityBlitResolver.Instance,
|
||||
MessagePack.Unity.UnityResolver.Instance,
|
||||
|
||||
// finaly use standard resolver
|
||||
StandardResolver.Instance);
|
||||
var options = MessagePackSerializerOptions.Default.WithResolver(resolver);
|
||||
|
||||
// Each time you serialize/deserialize, specify the options:
|
||||
byte[] msgpackBytes = MessagePackSerializer.Serialize(myObject, options);
|
||||
T myObject2 = MessagePackSerializer.Deserialize<MyObject>(msgpackBytes, options);
|
||||
```
|
||||
|
||||
Here is sample of use `DynamicEnumAsStringResolver` with `DynamicContractlessObjectResolver` (It is JSON.NET-like lightweight setting.)
|
||||
|
||||
```csharp
|
||||
// composite same as StandardResolver
|
||||
var resolver = new MessagePack.Resolvers.CompositeResolver();
|
||||
resolver.RegisterResolver(
|
||||
MessagePack.Resolvers.BuiltinResolver.Instance,
|
||||
MessagePack.Resolvers.AttributeFormatterResolver.Instance,
|
||||
|
||||
// replace enum resolver
|
||||
MessagePack.Resolvers.DynamicEnumAsStringResolver.Instance,
|
||||
|
||||
MessagePack.Resolvers.DynamicGenericResolver.Instance,
|
||||
MessagePack.Resolvers.DynamicUnionResolver.Instance,
|
||||
MessagePack.Resolvers.DynamicObjectResolver.Instance,
|
||||
|
||||
MessagePack.Resolvers.PrimitiveObjectResolver.Instance,
|
||||
|
||||
// final fallback(last priority)
|
||||
MessagePack.Resolvers.DynamicContractlessObjectResolver.Instance);
|
||||
```
|
||||
|
||||
If you want to make your extension package, you should write both the formatter and resolver
|
||||
for easier consumption.
|
||||
Here is sample of a resolver:
|
||||
|
||||
```csharp
|
||||
public class SampleCustomResolver : IFormatterResolver
|
||||
{
|
||||
// Resolver should be singleton.
|
||||
public static readonly IFormatterResolver Instance = new SampleCustomResolver();
|
||||
|
||||
private SampleCustomResolver()
|
||||
{
|
||||
}
|
||||
|
||||
// GetFormatter<T>'s get cost should be minimized so use type cache.
|
||||
public IMessagePackFormatter<T> GetFormatter<T>()
|
||||
{
|
||||
return FormatterCache<T>.Formatter;
|
||||
}
|
||||
|
||||
private static class FormatterCache<T>
|
||||
{
|
||||
public static readonly IMessagePackFormatter<T> Formatter;
|
||||
|
||||
// generic's static constructor should be minimized for reduce type generation size!
|
||||
// use outer helper method.
|
||||
static FormatterCache()
|
||||
{
|
||||
Formatter = (IMessagePackFormatter<T>)SampleCustomResolverGetFormatterHelper.GetFormatter(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SampleCustomResolverGetFormatterHelper
|
||||
{
|
||||
// If type is concrete type, use type-formatter map
|
||||
static readonly Dictionary<Type, object> formatterMap = new Dictionary<Type, object>()
|
||||
{
|
||||
{typeof(FileInfo), new FileInfoFormatter()}
|
||||
// add more your own custom serializers.
|
||||
};
|
||||
|
||||
internal static object GetFormatter(Type t)
|
||||
{
|
||||
object formatter;
|
||||
if (formatterMap.TryGetValue(t, out formatter))
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
|
||||
// If target type is generics, use MakeGenericType.
|
||||
if (t.IsGenericParameter && t.GetGenericTypeDefinition() == typeof(ValueTuple<,>))
|
||||
{
|
||||
return Activator.CreateInstance(typeof(ValueTupleFormatter<,>).MakeGenericType(t.GenericTypeArguments));
|
||||
}
|
||||
|
||||
// If type can not get, must return null for fallback mecanism.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
11
doc/rpc.md
11
doc/rpc.md
|
@ -1,11 +0,0 @@
|
|||
# RPC
|
||||
|
||||
MessagePack advocated [MessagePack RPC](https://github.com/msgpack-rpc/msgpack-rpc), but formulation is stopped and it is not widely used.
|
||||
|
||||
## MagicOnion
|
||||
|
||||
I've created gRPC based MessagePack HTTP/2 RPC streaming framework called [MagicOnion](https://github.com/neuecc/MagicOnion). gRPC usually communicates with Protocol Buffers using IDL. But MagicOnion uses MessagePack for C# and does not needs IDL. If communicates C# to C#, schemaless(C# classes as schema) is better than IDL.
|
||||
|
||||
## StreamJsonRpc
|
||||
|
||||
The StreamJsonRpc library is based on [JSON-RPC](https://www.jsonrpc.org/) and includes [a pluggable formatter architecture](https://github.com/microsoft/vs-streamjsonrpc/blob/master/doc/extensibility.md#alternative-formatters) and includes [a sample MessagePack plugin](https://github.com/microsoft/vs-streamjsonrpc/blob/master/src/StreamJsonRpc.Tests/MessagePackFormatter.cs).
|
|
@ -1,65 +0,0 @@
|
|||
Object Serialization
|
||||
---
|
||||
MessagePack for C# can serialize your own public `Class` or `Struct`. Serialization target must marks `[MessagePackObject]` and `[Key]`. Key type can choose int or string. If key type is int, serialized format is used array. If key type is string, serialized format is used map. If you define `[MessagePackObject(keyAsPropertyName: true)]`, does not require `KeyAttribute`.
|
||||
|
||||
```csharp
|
||||
[MessagePackObject]
|
||||
public class Sample1
|
||||
{
|
||||
[Key(0)]
|
||||
public int Foo { get; set; }
|
||||
[Key(1)]
|
||||
public int Bar { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class Sample2
|
||||
{
|
||||
[Key("foo")]
|
||||
public int Foo { get; set; }
|
||||
[Key("bar")]
|
||||
public int Bar { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject(keyAsPropertyName: true)]
|
||||
public class Sample3
|
||||
{
|
||||
// no needs KeyAttribute
|
||||
public int Foo { get; set; }
|
||||
|
||||
// If ignore public member, you can use IgnoreMemberAttribute
|
||||
[IgnoreMember]
|
||||
public int Bar { get; set; }
|
||||
}
|
||||
|
||||
// [10,20]
|
||||
Console.WriteLine(MessagePackSerializer.ToJson(new Sample1 { Foo = 10, Bar = 20 }));
|
||||
|
||||
// {"foo":10,"bar":20}
|
||||
Console.WriteLine(MessagePackSerializer.ToJson(new Sample2 { Foo = 10, Bar = 20 }));
|
||||
|
||||
// {"Foo":10}
|
||||
Console.WriteLine(MessagePackSerializer.ToJson(new Sample3 { Foo = 10, Bar = 20 }));
|
||||
```
|
||||
|
||||
All patterns serialization target are public instance member(field or property). If you want to avoid serialization target, you can add `[IgnoreMember]` to target member.
|
||||
|
||||
> target class must be public, does not allows private, internal class.
|
||||
|
||||
Which should uses int key or string key? I recommend use int key because faster and compact than string key. But string key has key name information, it is useful for debugging.
|
||||
|
||||
MessagePackSerializer requests target must put attribute is for robustness. If class is grown, you need to be conscious of versioning. MessagePackSerializer uses default value if key does not exists. If uses int key, should be start from 0 and should be sequential. If unnecessary properties come out, please make a missing number. Reuse is bad. Also, if Int Key's jump number is too large, it affects binary size.
|
||||
|
||||
```csharp
|
||||
[MessagePackObject]
|
||||
public class IntKeySample
|
||||
{
|
||||
[Key(3)]
|
||||
public int A { get; set; }
|
||||
[Key(10)]
|
||||
public int B { get; set; }
|
||||
}
|
||||
|
||||
// [null,null,null,0,null,null,null,null,null,null,0]
|
||||
Console.WriteLine(MessagePackSerializer.ToJson(new IntKeySample()));
|
||||
```
|
48
doc/unity.md
48
doc/unity.md
|
@ -1,48 +0,0 @@
|
|||
# Unity support
|
||||
|
||||
You can install by package and includes source code. If build target as PC, you can use as is but if build target uses IL2CPP, you can not use `Dynamic***Resolver` so use pre-code generation. Please see [pre-code generation section](aot.md).
|
||||
|
||||
In Unity, MessagePackSerializer can serialize `Vector2`, `Vector3`, `Vector4`, `Quaternion`, `Color`, `Bounds`, `Rect`, `AnimationCurve`, `Keyframe`, `Matrix4x4`, `Gradient`, `Color32`, `RectOffset`, `LayerMask`, `Vector2Int`, `Vector3Int`, `RangeInt`, `RectInt`, `BoundsInt` and there nullable, there array, there list by built-in extension `UnityResolver`. It is included StandardResolver by default.
|
||||
|
||||
MessagePack for C# has additional unsafe extension. `UnsafeBlitResolver` is special resolver for extremely fast unsafe serialization/deserialization for struct array.
|
||||
|
||||
![image](https://cloud.githubusercontent.com/assets/46207/23837633/76589924-07ce-11e7-8b26-e50eab548938.png)
|
||||
|
||||
x20 faster Vector3[] serialization than native JsonUtility. If use `UnsafeBlitResolver`, serialize special format(ext:typecode 30~39) `Vector2[]`, `Vector3[]`, `Quaternion[]`, `Color[]`, `Bounds[]`, `Rect[]`. If use `UnityBlitWithPrimitiveArrayResolver`, supports `int[]`, `float[]`, `double[]` too. This special feature is useful for serialize Mesh(many Vector3[]) or many transform position.
|
||||
|
||||
If you want to use unsafe resolver, you must enables unsafe option and define additional symbols. At first, write `-unsafe` on `smcs.rsp`, `gmcs.rsp` etc. And define `ENABLE_UNSAFE_MSGPACK` symbol.
|
||||
|
||||
![image](https://cloud.githubusercontent.com/assets/46207/23837456/fc01c828-07cb-11e7-92bf-f23eb2575115.png)
|
||||
|
||||
Here is sample of configuration.
|
||||
|
||||
```csharp
|
||||
Resolvers.CompositeResolver.RegisterAndSetAsDefault(
|
||||
MessagePack.Unity.UnityResolver.Instance,
|
||||
MessagePack.Unity.Extension.UnityBlitWithPrimitiveArrayResolver.Instance,
|
||||
|
||||
// If PC, use StandardResolver
|
||||
// MessagePack.Resolvers.StandardResolver.Instance,
|
||||
|
||||
// If IL2CPP, Builtin + GeneratedResolver.
|
||||
// MessagePack.Resolvers.BuiltinResolver.Instance,
|
||||
);
|
||||
```
|
||||
|
||||
`MessagePack.UnityShims` NuGet package is for .NET ServerSide serialization support to communicate with Unity. It includes shim of Vector3 etc and Safe/Unsafe serialization extension.
|
||||
|
||||
If you want to share class between Unity and Server, you can use `SharedProject` or `Reference as Link` or new MSBuild(VS2017)'s wildcard reference etc. Anyway you need to source-code level share. This is sample project structure of use SharedProject.
|
||||
|
||||
- SharedProject(source code sharing)
|
||||
- Source codes of server-client shared
|
||||
- ServerProject(.NET 4.6/.NET Core/.NET Standard)
|
||||
- [SharedProject]
|
||||
- [MessagePack]
|
||||
- [MessagePack.UnityShims]
|
||||
- ClientDllProject(.NET 3.5)
|
||||
- [SharedProject]
|
||||
- [MessagePack](not dll, use MessagePack.unitypackage's sourcecodes)
|
||||
- Unity
|
||||
- [Builded ClientDll]
|
||||
|
||||
Other ways, use plain POCO by `DataContract`/`DataMember` can use.
|
Загрузка…
Ссылка в новой задаче