diff options
author | neuecc <ils@neue.cc> | 2017-06-08 10:37:40 +0300 |
---|---|---|
committer | neuecc <ils@neue.cc> | 2017-06-08 10:37:40 +0300 |
commit | 32a2a2a69fbc289af73bc153e1db1ceea9075a1e (patch) | |
tree | 8e96430714e3aff0cdb725c203279377e55c32c2 | |
parent | ca47068b8107a83171acdd8afd98cf9dc85744fb (diff) |
1.3.0, add MessagePackFormatterAttributev1.3.0
-rw-r--r-- | README.md | 38 | ||||
-rw-r--r-- | nuget/MessagePack.AspNetCoreMvcFormatter.nuspec | 4 | ||||
-rw-r--r-- | nuget/MessagePack.ImmutableCollection.nuspec | 8 | ||||
-rw-r--r-- | nuget/MessagePack.ReactiveProperty.nuspec | 8 | ||||
-rw-r--r-- | nuget/MessagePack.UnityShims.nuspec | 8 | ||||
-rw-r--r-- | nuget/MessagePack.nuspec | 2 | ||||
-rw-r--r-- | nuget/push.bat | 10 | ||||
-rw-r--r-- | sandbox/Sandbox/Program.cs | 27 | ||||
-rw-r--r-- | sandbox/SharedData/packages.config | 2 | ||||
-rw-r--r-- | src/MessagePack.UnityClient/MessagePack.UnityClient.csproj | 1 | ||||
-rw-r--r-- | src/MessagePack/Attributes.cs | 11 | ||||
-rw-r--r-- | src/MessagePack/Resolvers/AttributeFormatterResolver.cs | 40 | ||||
-rw-r--r-- | src/MessagePack/Resolvers/StandardResolver.cs | 4 | ||||
-rw-r--r-- | tests/MessagePack.Tests/MessagePack.Tests.csproj | 1 | ||||
-rw-r--r-- | tests/MessagePack.Tests/SpecifiedFormatterResolverTest.cs | 152 |
15 files changed, 293 insertions, 23 deletions
@@ -672,9 +672,10 @@ 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 -> 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` -> `DynamicContractlessObjectResolver`. 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`. | +| AttributeFormatterResolver | Get formatter from `[MessagePackFormatter]` attribute. | | CompositeResolver | Singleton helper of setup custom resolvers. You can use `Register` or `RegisterAndSetAsDefault` API. | | NativeDateTimeResolver | Serialize by .NET native DateTime binary format. | | OldSpecResolver | str and bin serialize/deserialize follows old messagepack spec(use raw format) | @@ -838,6 +839,40 @@ internal static class SampleCustomResolverGetFormatterHelper } ``` +MessaegPackFormatterAttribute +--- +MessaegPackFormatterAttribute is lightweight extension point of class, struct, interface, enum. This is like JSON.NET's JsonConverterAttribute. For example, serialize private field. + +```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 int Serialize(ref byte[] bytes, int offset, CustomObject value, IFormatterResolver formatterResolver) + { + return formatterResolver.GetFormatterWithVerify<string>().Serialize(ref bytes, offset, value.internalId, formatterResolver); + } + + public CustomObject Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var id = formatterResolver.GetFormatterWithVerify<string>().Deserialize(bytes, offset, formatterResolver, out readSize); + return new CustomObject { internalId = id }; + } + } +} +``` + +Formatter is retrieved by `AttributeFormatterResolver`, it is included in `StandardResolver`. + for Unity --- 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](https://github.com/neuecc/MessagePack-CSharp#pre-code-generationunityxamarin-supports). @@ -935,6 +970,7 @@ MessagePack.Resolvers.CompositeResolver.RegisterAndSetAsDefault( // finally, use builtin/primitive resolver(don't use StandardResolver, it includes dynamic generation) MessagePack.Resolvers.BuiltinResolver.Instance, + AttributeFormatterResolver.Instance, MessagePack.Resolvers.PrimitiveObjectResolver.Instance ); ``` diff --git a/nuget/MessagePack.AspNetCoreMvcFormatter.nuspec b/nuget/MessagePack.AspNetCoreMvcFormatter.nuspec index 075dd8c1..bd11d0e2 100644 --- a/nuget/MessagePack.AspNetCoreMvcFormatter.nuspec +++ b/nuget/MessagePack.AspNetCoreMvcFormatter.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MessagePack.AspNetCoreMvcFormatter</id> - <version>1.2.3</version> + <version>1.3.0</version> <title>ASP.NET Core MVC Input/Output MessagePack formatter</title> <authors>neuecc</authors> <owners>neuecc</owners> @@ -13,7 +13,7 @@ <tags>MsgPack, MessagePack, Serialization, Formatter, Serializer, aspnetcore, aspnetcoremvc</tags> <dependencies> <group targetFramework=".NETStandard1.4"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> <dependency id="Microsoft.AspNetCore.Mvc.Abstractions" version="1.2.0" /> </group> </dependencies> diff --git a/nuget/MessagePack.ImmutableCollection.nuspec b/nuget/MessagePack.ImmutableCollection.nuspec index 2342d4e4..d9b231fd 100644 --- a/nuget/MessagePack.ImmutableCollection.nuspec +++ b/nuget/MessagePack.ImmutableCollection.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MessagePack.ImmutableCollection</id> - <version>1.2.3</version> + <version>1.3.0</version> <title>MessagePack for C# Extension Support for ImmutableCollection</title> <authors>neuecc</authors> <owners>neuecc</owners> @@ -17,15 +17,15 @@ </frameworkAssemblies> <dependencies> <group targetFramework=".NETFramework4.7"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> <dependency id="System.Collections.Immutable" version="1.3.1" /> </group> <group targetFramework=".NETFramework4.5"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> <dependency id="System.Collections.Immutable" version="1.3.1" /> </group> <group targetFramework=".NETStandard1.4"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> <dependency id="System.Collections.Immutable" version="1.3.1" /> </group> </dependencies> diff --git a/nuget/MessagePack.ReactiveProperty.nuspec b/nuget/MessagePack.ReactiveProperty.nuspec index f5ddb42e..855233b1 100644 --- a/nuget/MessagePack.ReactiveProperty.nuspec +++ b/nuget/MessagePack.ReactiveProperty.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MessagePack.ReactiveProperty</id> - <version>1.2.3</version> + <version>1.3.0</version> <title>MessagePack for C# Extension Support for ReactiveProperty</title> <authors>neuecc</authors> <owners>neuecc</owners> @@ -17,15 +17,15 @@ </frameworkAssemblies> <dependencies> <group targetFramework=".NETFramework4.7"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> <dependency id="ReactiveProperty" version="3.5.1" /> </group> <group targetFramework=".NETFramework4.5"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> <dependency id="ReactiveProperty" version="3.5.1" /> </group> <group targetFramework=".NETStandard1.4"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> <dependency id="ReactiveProperty" version="3.5.1" /> </group> </dependencies> diff --git a/nuget/MessagePack.UnityShims.nuspec b/nuget/MessagePack.UnityShims.nuspec index bcbc3fb1..b6d8e7df 100644 --- a/nuget/MessagePack.UnityShims.nuspec +++ b/nuget/MessagePack.UnityShims.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MessagePack.UnityShims</id> - <version>1.2.3</version> + <version>1.3.0</version> <title>MessagePack for C# Extension Support for Unity(add pseudo Vector type and fast Vectory[] extension formatter)</title> <authors>neuecc</authors> <owners>neuecc</owners> @@ -17,13 +17,13 @@ </frameworkAssemblies> <dependencies> <group targetFramework=".NETFramework4.7"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> </group> <group targetFramework=".NETFramework4.5"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> </group> <group targetFramework=".NETStandard1.4"> - <dependency id="MessagePack" version="1.2.3" /> + <dependency id="MessagePack" version="1.3.0" /> </group> </dependencies> </metadata> diff --git a/nuget/MessagePack.nuspec b/nuget/MessagePack.nuspec index 141ead1d..8986ae71 100644 --- a/nuget/MessagePack.nuspec +++ b/nuget/MessagePack.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MessagePack</id> - <version>1.2.3</version> + <version>1.3.0</version> <title>MessagePack for C#</title> <authors>neuecc</authors> <owners>neuecc</owners> diff --git a/nuget/push.bat b/nuget/push.bat index afafe812..c153c253 100644 --- a/nuget/push.bat +++ b/nuget/push.bat @@ -1,6 +1,6 @@ -nuget push MessagePack.1.2.3.nupkg -Source https://www.nuget.org/api/v2/package -nuget push MessagePack.ImmutableCollection.1.2.3.nupkg -Source https://www.nuget.org/api/v2/package -nuget push MessagePack.ReactiveProperty.1.2.3.nupkg -Source https://www.nuget.org/api/v2/package -nuget push MessagePack.UnityShims.1.2.3.nupkg -Source https://www.nuget.org/api/v2/package -nuget push MessagePack.AspNetCoreMvcFormatter.1.2.3.nupkg -Source https://www.nuget.org/api/v2/package +nuget push MessagePack.1.3.0.nupkg -Source https://www.nuget.org/api/v2/package +nuget push MessagePack.ImmutableCollection.1.3.0.nupkg -Source https://www.nuget.org/api/v2/package +nuget push MessagePack.ReactiveProperty.1.3.0.nupkg -Source https://www.nuget.org/api/v2/package +nuget push MessagePack.UnityShims.1.3.0.nupkg -Source https://www.nuget.org/api/v2/package +nuget push MessagePack.AspNetCoreMvcFormatter.1.3.0.nupkg -Source https://www.nuget.org/api/v2/package REM nuget push MessagePackAnalyzer.1.6.0.nupkg -Source https://www.nuget.org/api/v2/package
\ No newline at end of file diff --git a/sandbox/Sandbox/Program.cs b/sandbox/Sandbox/Program.cs index 5e2f9873..e29f7547 100644 --- a/sandbox/Sandbox/Program.cs +++ b/sandbox/Sandbox/Program.cs @@ -228,6 +228,33 @@ namespace Sandbox } + [MessagePackFormatter(typeof(CustomObjectFormatter))] + public class CustomObject + { + string internalId; + + public CustomObject() + { + this.internalId = Guid.NewGuid().ToString(); + } + + // serialize/deserialize internal field. + class CustomObjectFormatter : IMessagePackFormatter<CustomObject> + { + public int Serialize(ref byte[] bytes, int offset, CustomObject value, IFormatterResolver formatterResolver) + { + return formatterResolver.GetFormatterWithVerify<string>().Serialize(ref bytes, offset, value.internalId, formatterResolver); + } + + public CustomObject Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var id = formatterResolver.GetFormatterWithVerify<string>().Deserialize(bytes, offset, formatterResolver, out readSize); + return new CustomObject { internalId = id }; + } + } + } + + class Program { static void Main(string[] args) diff --git a/sandbox/SharedData/packages.config b/sandbox/SharedData/packages.config index 9b66c2a1..ad3acc03 100644 --- a/sandbox/SharedData/packages.config +++ b/sandbox/SharedData/packages.config @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="MessagePack" version="1.2.3" targetFramework="net461" /> + <package id="MessagePack" version="1.3.0" targetFramework="net461" /> <package id="System.Threading.Tasks.Extensions" version="4.3.0" targetFramework="net461" /> <package id="System.ValueTuple" version="4.3.0" targetFramework="net461" /> </packages>
\ No newline at end of file diff --git a/src/MessagePack.UnityClient/MessagePack.UnityClient.csproj b/src/MessagePack.UnityClient/MessagePack.UnityClient.csproj index d306e757..703a924f 100644 --- a/src/MessagePack.UnityClient/MessagePack.UnityClient.csproj +++ b/src/MessagePack.UnityClient/MessagePack.UnityClient.csproj @@ -123,6 +123,7 @@ <Compile Include="Assets\Scripts\MessagePack\MessagePackSerializer.NonGeneric.cs" /> <Compile Include="Assets\Scripts\MessagePack\MessagePackSerializer.cs" /> <Compile Include="Assets\Scripts\MessagePack\Nil.cs" /> + <Compile Include="Assets\Scripts\MessagePack\Resolvers\AttributeFormatterResolver.cs" /> <Compile Include="Assets\Scripts\MessagePack\Resolvers\BuiltinResolver.cs" /> <Compile Include="Assets\Scripts\MessagePack\Resolvers\CompositeResolver.cs" /> <Compile Include="Assets\Scripts\MessagePack\Resolvers\DynamicEnumAsStringResolver.cs" /> diff --git a/src/MessagePack/Attributes.cs b/src/MessagePack/Attributes.cs index 324e55a1..c0dea5b8 100644 --- a/src/MessagePack/Attributes.cs +++ b/src/MessagePack/Attributes.cs @@ -53,4 +53,15 @@ namespace MessagePack { } + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Enum, AllowMultiple = false, Inherited = true)] + public class MessagePackFormatterAttribute : Attribute + { + public Type FormatterType { get; private set; } + + public MessagePackFormatterAttribute(Type formatterType) + { + this.FormatterType = formatterType; + } + } }
\ No newline at end of file diff --git a/src/MessagePack/Resolvers/AttributeFormatterResolver.cs b/src/MessagePack/Resolvers/AttributeFormatterResolver.cs new file mode 100644 index 00000000..8bdc3f1b --- /dev/null +++ b/src/MessagePack/Resolvers/AttributeFormatterResolver.cs @@ -0,0 +1,40 @@ +using MessagePack.Formatters; +using System; +using System.Reflection; + +namespace MessagePack.Resolvers +{ + /// <summary> + /// Get formatter from [MessaegPackFromatter] attribute. + /// </summary> + public class AttributeFormatterResolver : IFormatterResolver + { + public static IFormatterResolver Instance = new AttributeFormatterResolver(); + + AttributeFormatterResolver() + { + + } + + public IMessagePackFormatter<T> GetFormatter<T>() + { + return FormatterCache<T>.formatter; + } + + static class FormatterCache<T> + { + public static readonly IMessagePackFormatter<T> formatter; + + static FormatterCache() + { + var attr = typeof(T).GetTypeInfo().GetCustomAttribute<MessagePackFormatterAttribute>(); + if (attr == null) + { + return; + } + + formatter = (IMessagePackFormatter<T>)Activator.CreateInstance(attr.FormatterType); + } + } + } +}
\ No newline at end of file diff --git a/src/MessagePack/Resolvers/StandardResolver.cs b/src/MessagePack/Resolvers/StandardResolver.cs index 2fae4598..bd489e1f 100644 --- a/src/MessagePack/Resolvers/StandardResolver.cs +++ b/src/MessagePack/Resolvers/StandardResolver.cs @@ -3,7 +3,7 @@ namespace MessagePack.Resolvers { /// <summary> - /// Default composited resolver, builtin -> dynamic enum -> dynamic generic -> dynamic union -> dynamic object. + /// Default composited resolver, builtin -> attribute -> dynamic enum -> dynamic generic -> dynamic union -> dynamic object -> primitive. /// </summary> public class StandardResolver : IFormatterResolver { @@ -13,6 +13,8 @@ namespace MessagePack.Resolvers { BuiltinResolver.Instance, // Try Builtin + AttributeFormatterResolver.Instance, // Try use [MessagePackFormatter] + #if !NETSTANDARD1_4 MessagePack.Unity.UnityResolver.Instance, #endif diff --git a/tests/MessagePack.Tests/MessagePack.Tests.csproj b/tests/MessagePack.Tests/MessagePack.Tests.csproj index c177d815..e09f77e9 100644 --- a/tests/MessagePack.Tests/MessagePack.Tests.csproj +++ b/tests/MessagePack.Tests/MessagePack.Tests.csproj @@ -120,6 +120,7 @@ <Compile Include="PrimitivelikeFormatterTest.cs" /> <Compile Include="PrimitiveResolverTest.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="SpecifiedFormatterResolverTest.cs" /> <Compile Include="UnionResolverTest.cs" /> <Compile Include="Utils\ChainingAssertion.Ext.cs" /> <Compile Include="Utils\ChainingAssertion.Xunit.cs" /> diff --git a/tests/MessagePack.Tests/SpecifiedFormatterResolverTest.cs b/tests/MessagePack.Tests/SpecifiedFormatterResolverTest.cs new file mode 100644 index 00000000..ce0c693e --- /dev/null +++ b/tests/MessagePack.Tests/SpecifiedFormatterResolverTest.cs @@ -0,0 +1,152 @@ +using MessagePack.Formatters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace MessagePack.Tests +{ + + public class SpecifiedFormatterResolverTest + { + [MessagePackFormatter(typeof(NoObjectFormatter))] + class CustomClassObject + { + int X; + + public CustomClassObject(int x) + { + this.X = x; + } + + public int GetX() + { + return X; + } + + class NoObjectFormatter : IMessagePackFormatter<CustomClassObject> + { + public CustomClassObject Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var r = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + return new CustomClassObject(r); + } + + public int Serialize(ref byte[] bytes, int offset, CustomClassObject value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt32(ref bytes, offset, value.X); + } + } + } + + [MessagePackFormatter(typeof(CustomStructObjectFormatter))] + struct CustomStructObject + { + int X; + + public CustomStructObject(int x) + { + this.X = x; + } + + public int GetX() + { + return X; + } + + class CustomStructObjectFormatter : IMessagePackFormatter<CustomStructObject> + { + public CustomStructObject Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var r = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + return new CustomStructObject(r); + } + + public int Serialize(ref byte[] bytes, int offset, CustomStructObject value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt32(ref bytes, offset, value.X); + } + } + } + + [MessagePackFormatter(typeof(CustomEnumObjectFormatter))] + enum CustomyEnumObject + { + A = 0, B = 1, C = 2 + } + + class CustomEnumObjectFormatter : IMessagePackFormatter<CustomyEnumObject> + { + public CustomyEnumObject Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var r = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + if (r == 0) + { + return CustomyEnumObject.A; + } + else if (r == 2) + { + return CustomyEnumObject.C; + } + return CustomyEnumObject.B; + } + + public int Serialize(ref byte[] bytes, int offset, CustomyEnumObject value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt32(ref bytes, offset, (int)value); + } + } + + [MessagePackFormatter(typeof(CustomInterfaceObjectFormatter))] + interface ICustomInterfaceObject + { + int A { get; } + } + + class CustomInterfaceObjectFormatter : IMessagePackFormatter<ICustomInterfaceObject> + { + public ICustomInterfaceObject Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var r = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + return new InheritDefault(r); + } + + public int Serialize(ref byte[] bytes, int offset, ICustomInterfaceObject value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt32(ref bytes, offset, value.A); + } + } + + class InheritDefault : ICustomInterfaceObject + { + public int A { get; } + + public InheritDefault(int a) + { + this.A = a; + } + } + + class HogeMoge : ICustomInterfaceObject + { + public int A { get; set; } + } + + T Convert<T>(T value) + { + return MessagePackSerializer.Deserialize<T>(MessagePackSerializer.Serialize(value, MessagePack.Resolvers.StandardResolver.Instance), MessagePack.Resolvers.StandardResolver.Instance); + } + + [Fact] + public void CustomFormatters() + { + Convert(new CustomClassObject(999)).GetX().Is(999); + Convert(new CustomStructObject(1234)).GetX().Is(1234); + Convert(CustomyEnumObject.C).Is(CustomyEnumObject.C); + Convert((CustomyEnumObject)(1234)).Is(CustomyEnumObject.B); + Convert<ICustomInterfaceObject>(new HogeMoge { A = 999 }).A.Is(999); + } + } +} |