Skip to content

Commit 033d6d8

Browse files
author
amirsolhi
committed
MemoryPack serializer
1 parent 4cc0ab9 commit 033d6d8

File tree

9 files changed

+277
-12
lines changed

9 files changed

+277
-12
lines changed

EasyCaching.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
Microsoft Visual Studio Solution File, Format Version 12.00
22
# Visual Studio Version 17
33
VisualStudioVersion = 17.2.32616.157
44
MinimumVisualStudioVersion = 10.0.40219.1
@@ -76,6 +76,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Bus.Zookeeper",
7676
EndProject
7777
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.FasterKv", "src\EasyCaching.FasterKv\EasyCaching.FasterKv.csproj", "{7191E567-38DF-4879-82E1-73EC618AFCAC}"
7878
EndProject
79+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyCaching.Serialization.MemoryPack", "serialization\EasyCaching.Serialization.MemoryPack\EasyCaching.Serialization.MemoryPack.csproj", "{EEF22C21-F380-4980-B72C-F14488369333}"
80+
EndProject
7981
Global
8082
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8183
Debug|Any CPU = Debug|Any CPU
@@ -202,6 +204,10 @@ Global
202204
{7191E567-38DF-4879-82E1-73EC618AFCAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
203205
{7191E567-38DF-4879-82E1-73EC618AFCAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
204206
{7191E567-38DF-4879-82E1-73EC618AFCAC}.Release|Any CPU.Build.0 = Release|Any CPU
207+
{EEF22C21-F380-4980-B72C-F14488369333}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
208+
{EEF22C21-F380-4980-B72C-F14488369333}.Debug|Any CPU.Build.0 = Debug|Any CPU
209+
{EEF22C21-F380-4980-B72C-F14488369333}.Release|Any CPU.ActiveCfg = Release|Any CPU
210+
{EEF22C21-F380-4980-B72C-F14488369333}.Release|Any CPU.Build.0 = Release|Any CPU
205211
EndGlobalSection
206212
GlobalSection(SolutionProperties) = preSolution
207213
HideSolutionNode = FALSE
@@ -237,6 +243,7 @@ Global
237243
{F7FBADEB-D766-4595-949A-07104B52692C} = {B337509B-75F9-4851-821F-9BBE87C4E4BC}
238244
{5E488583-391E-4E15-83C1-7301B4FE79AE} = {B337509B-75F9-4851-821F-9BBE87C4E4BC}
239245
{7191E567-38DF-4879-82E1-73EC618AFCAC} = {A0F5CC7E-155F-4726-8DEB-E966950B3FE9}
246+
{EEF22C21-F380-4980-B72C-F14488369333} = {15070C49-A507-4844-BCFE-D319CFBC9A63}
240247
EndGlobalSection
241248
GlobalSection(ExtensibilityGlobals) = postSolution
242249
SolutionGuid = {63A57886-054B-476C-AAE1-8D7C8917682E}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using MemoryPack;
2+
3+
namespace EasyCaching.Serialization.MemoryPack;
4+
5+
/// <summary>
6+
/// EasyCaching memory pack serializer options.
7+
/// </summary>
8+
public record EasyCachingMemPackSerializerOptions
9+
{
10+
public StringEncoding StringEncoding { set; get; }
11+
}
12+
13+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using MemoryPack;
2+
using EasyCaching.Core.Configurations;
3+
using EasyCaching.Serialization.Json;
4+
5+
namespace EasyCaching.Serialization.MemoryPack;
6+
7+
/// <summary>
8+
/// Easy caching options extensions.
9+
/// </summary>
10+
public static class EasyCachingOptionsExtensions
11+
{
12+
/// <summary>
13+
/// Withs the memory pack serializer.
14+
/// </summary>
15+
/// <param name="options">Options.</param>
16+
/// <param name="name">The name of this serializer instance.</param>
17+
public static EasyCachingOptions WithMemoryPack(this EasyCachingOptions options, string name = "mempack")
18+
{
19+
options.RegisterExtension(new MemoryPackOptionsExtension(name, null));
20+
21+
return options;
22+
}
23+
24+
/// <summary>
25+
/// Withs the memory pack serializer.
26+
/// </summary>
27+
/// <param name="options">Options.</param>
28+
/// <param name="configure">Configure serializer settings.</param>
29+
/// <param name="name">The name of this serializer instance.</param>
30+
public static EasyCachingOptions WithMemoryPack(this EasyCachingOptions options, Action<EasyCachingMemPackSerializerOptions> serializerOptions, string name)
31+
{
32+
options.RegisterExtension(new MemoryPackOptionsExtension(name, serializerOptions));
33+
34+
return options;
35+
}
36+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
namespace EasyCaching.Serialization.Json;
2+
3+
using System;
4+
using EasyCaching.Core.Configurations;
5+
using EasyCaching.Core.Serialization;
6+
using EasyCaching.Serialization.MemoryPack;
7+
using global::MemoryPack;
8+
using Microsoft.Extensions.DependencyInjection;
9+
10+
/// <summary>
11+
/// MemoryPack options extension.
12+
/// </summary>
13+
internal sealed class MemoryPackOptionsExtension : IEasyCachingOptionsExtension
14+
{
15+
/// <summary>
16+
/// The name.
17+
/// </summary>
18+
private readonly string _name;
19+
20+
/// <summary>
21+
/// The configure.
22+
/// </summary>
23+
private readonly Action<EasyCachingMemPackSerializerOptions> _configure;
24+
25+
/// <summary>
26+
/// Initializes a new instance of the <see cref="T:EasyCaching.Serialization.MemoryPack.MemoryPackOptionsExtension"/> class.
27+
/// </summary>
28+
/// <param name="name">Name.</param>
29+
/// <param name="configure">Configure.</param>
30+
public MemoryPackOptionsExtension(string name, Action<EasyCachingMemPackSerializerOptions> configure)
31+
{
32+
this._name = name;
33+
this._configure = configure;
34+
}
35+
36+
/// <summary>
37+
/// Adds the services.
38+
/// </summary>
39+
/// <param name="services">Services.</param>
40+
public void AddServices(IServiceCollection services)
41+
{
42+
Action<EasyCachingMemPackSerializerOptions> configure = _configure ?? (_ => { });
43+
44+
services.AddOptions();
45+
services.Configure(_name, configure);
46+
47+
services.AddSingleton<IEasyCachingSerializer, DefaultMemoryPackSerializer>(x =>
48+
{
49+
var optionsMon = x.GetRequiredService<Microsoft.Extensions.Options.IOptionsMonitor<EasyCachingMemPackSerializerOptions>>();
50+
var easyCachingOptions = optionsMon.Get(_name);
51+
var options = new MemoryPackSerializerOptions { StringEncoding = easyCachingOptions.StringEncoding };
52+
return new DefaultMemoryPackSerializer(_name, options);
53+
});
54+
}
55+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using EasyCaching.Core.Serialization;
2+
using MemoryPack;
3+
4+
namespace EasyCaching.Serialization.MemoryPack;
5+
6+
/// <summary>
7+
/// Default MemoryPack serializer
8+
/// </summary>
9+
public class DefaultMemoryPackSerializer : IEasyCachingSerializer
10+
{
11+
private readonly string _name;
12+
private readonly MemoryPackSerializerOptions _memoryPackSerializerOptions;
13+
14+
public string Name => _name;
15+
16+
public DefaultMemoryPackSerializer(string name, MemoryPackSerializerOptions options = null)
17+
{
18+
_name = name;
19+
_memoryPackSerializerOptions = options;
20+
}
21+
22+
public T Deserialize<T>(byte[] bytes) => MemoryPackSerializer.Deserialize<T>(bytes, _memoryPackSerializerOptions);
23+
public object Deserialize(byte[] bytes, Type type) => MemoryPackSerializer.Deserialize(type, bytes, _memoryPackSerializerOptions);
24+
public object DeserializeObject(ArraySegment<byte> value) => throw new NotImplementedException("this is not supported in MemoryPack serializer");
25+
public byte[] Serialize<T>(T value) => MemoryPackSerializer.Serialize(value, _memoryPackSerializerOptions);
26+
27+
public ArraySegment<byte> SerializeObject(object obj)
28+
{
29+
var bytes = MemoryPackSerializer.Serialize(obj.GetType(), obj, _memoryPackSerializerOptions);
30+
return new ArraySegment<byte>(bytes);
31+
}
32+
}
33+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<ProjectReference Include="..\..\src\EasyCaching.Core\EasyCaching.Core.csproj" />
9+
</ItemGroup>
10+
<ItemGroup>
11+
<PackageReference Include="MemoryPack" Version="1.9.7" />
12+
</ItemGroup>
13+
</Project>

test/EasyCaching.UnitTests/EasyCaching.UnitTests.csproj

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,6 @@
3030
</ItemGroup>
3131

3232
<ItemGroup>
33-
<ProjectReference Include="..\..\bus\EasyCaching.Bus.CSRedis\EasyCaching.Bus.CSRedis.csproj" />
34-
<ProjectReference Include="..\..\bus\EasyCaching.Bus.RabbitMQ\EasyCaching.Bus.RabbitMQ.csproj" />
35-
<ProjectReference Include="..\..\bus\EasyCaching.Bus.Redis\EasyCaching.Bus.Redis.csproj" />
36-
<ProjectReference Include="..\..\interceptor\EasyCaching.Interceptor.AspectCore\EasyCaching.Interceptor.AspectCore.csproj" />
37-
<ProjectReference Include="..\..\interceptor\EasyCaching.Interceptor.Castle\EasyCaching.Interceptor.Castle.csproj" />
38-
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.Json\EasyCaching.Serialization.Json.csproj" />
39-
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.MessagePack\EasyCaching.Serialization.MessagePack.csproj" />
40-
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.Protobuf\EasyCaching.Serialization.Protobuf.csproj" />
41-
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.SystemTextJson\EasyCaching.Serialization.SystemTextJson.csproj" />
4233
<ProjectReference Include="..\..\src\EasyCaching.Core\EasyCaching.Core.csproj" />
4334
<ProjectReference Include="..\..\src\EasyCaching.FasterKv\EasyCaching.FasterKv.csproj" />
4435
<ProjectReference Include="..\..\src\EasyCaching.LiteDB\EasyCaching.LiteDB.csproj" />
@@ -51,4 +42,23 @@
5142
<ProjectReference Include="..\..\src\EasyCaching.CSRedis\EasyCaching.CSRedis.csproj" />
5243
<ProjectReference Include="..\..\src\EasyCaching.Disk\EasyCaching.Disk.csproj" />
5344
</ItemGroup>
45+
46+
<ItemGroup>
47+
<ProjectReference Include="..\..\bus\EasyCaching.Bus.CSRedis\EasyCaching.Bus.CSRedis.csproj" />
48+
<ProjectReference Include="..\..\bus\EasyCaching.Bus.RabbitMQ\EasyCaching.Bus.RabbitMQ.csproj" />
49+
<ProjectReference Include="..\..\bus\EasyCaching.Bus.Redis\EasyCaching.Bus.Redis.csproj" />
50+
</ItemGroup>
51+
52+
<ItemGroup>
53+
<ProjectReference Include="..\..\interceptor\EasyCaching.Interceptor.AspectCore\EasyCaching.Interceptor.AspectCore.csproj" />
54+
<ProjectReference Include="..\..\interceptor\EasyCaching.Interceptor.Castle\EasyCaching.Interceptor.Castle.csproj" />
55+
</ItemGroup>
56+
57+
<ItemGroup>
58+
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.Json\EasyCaching.Serialization.Json.csproj" />
59+
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.MessagePack\EasyCaching.Serialization.MessagePack.csproj" />
60+
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.MemoryPack\EasyCaching.Serialization.MemoryPack.csproj" />
61+
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.Protobuf\EasyCaching.Serialization.Protobuf.csproj" />
62+
<ProjectReference Include="..\..\serialization\EasyCaching.Serialization.SystemTextJson\EasyCaching.Serialization.SystemTextJson.csproj" />
63+
</ItemGroup>
5464
</Project>

test/EasyCaching.UnitTests/SerializerTests/BaseSerializerTest.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
using System;
44
using EasyCaching.Core.Serialization;
5+
using MemoryPack;
56
using ProtoBuf;
67
using Xunit;
78

@@ -38,7 +39,7 @@ public void SerializeObject_should_Succeed()
3839
}
3940

4041
[Fact]
41-
public void DeserializeObject_should_Succeed()
42+
public virtual void DeserializeObject_should_Succeed()
4243
{
4344
object obj = new Model { Prop = "abc" };
4445

@@ -76,7 +77,8 @@ public void Deserialize_String_Should_Succeed(string str)
7677

7778
[Serializable]
7879
[ProtoContract]
79-
public class Model
80+
[MemoryPackable]
81+
public partial class Model
8082
{
8183
[ProtoMember(1)]
8284
public string Prop { get; set; }
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using System;
2+
using EasyCaching.Serialization.MemoryPack;
3+
using MemoryPack;
4+
using Xunit;
5+
6+
namespace EasyCaching.UnitTests;
7+
8+
9+
public class MemoryPackSerializerTest : BaseSerializerTest
10+
{
11+
public MemoryPackSerializerTest()
12+
{
13+
_serializer = new DefaultMemoryPackSerializer("test");
14+
}
15+
16+
//This should be overrided becuse it is not supported by memory-pack
17+
public override void DeserializeObject_should_Succeed()
18+
{
19+
Person input = new("test", "test1");
20+
var serialized = _serializer.Serialize<Person>(input);
21+
22+
Assert.Throws<NotImplementedException>(() =>
23+
{
24+
_serializer.DeserializeObject(new System.ArraySegment<byte>(serialized));
25+
});
26+
}
27+
28+
[Fact]
29+
public void GivenSampleRecord_ShouldSerializeAndDeserializeSuccessfuly()
30+
{
31+
Person input = new("test", "test1");
32+
var bytes = _serializer.Serialize(input);
33+
34+
Person output = _serializer.Deserialize<Person>(bytes);
35+
36+
Assert.Equal(input, output);
37+
}
38+
39+
[Fact]
40+
public void GivenSampleRecord_ShouldHandleNestedObjectSuccessfuly()
41+
{
42+
NestedPerson item1 = new() { Name = "test", Lastname = "test1" };
43+
NestedPerson expected = new() { Name = "test2", Lastname = "test3", Inner = item1 };
44+
45+
var bytes = _serializer.Serialize(expected);
46+
47+
NestedPerson output = _serializer.Deserialize<NestedPerson>(bytes);
48+
49+
Assert.Equal(expected, output);
50+
}
51+
52+
[Fact]
53+
public void GivenSampleInput_ShouldHandleCircularRefSuccessfuly()
54+
{
55+
CircularPerson person = new CircularPerson()
56+
{
57+
Name = "test"
58+
};
59+
60+
person.Self = person;
61+
62+
var bytes = _serializer.Serialize(person);
63+
var output = _serializer.Deserialize<CircularPerson>(bytes);
64+
65+
bool expected =
66+
person.Name == output.Name &&
67+
output.Self == output &&
68+
output.Name == output.Self.Name;
69+
70+
Assert.True(expected);
71+
}
72+
}
73+
74+
#region Test Models
75+
[MemoryPackable(GenerateType.CircularReference)]
76+
internal partial class CircularPerson
77+
{
78+
[MemoryPackOrder(0)]
79+
public string Name { set; get; }
80+
[MemoryPackOrder(1)]
81+
public CircularPerson Self { set; get; }
82+
}
83+
84+
[MemoryPackable]
85+
internal partial record struct Person(string Name, string Lastname);
86+
87+
[MemoryPackable]
88+
internal partial record class NestedPerson
89+
{
90+
public string Name { set; get; }
91+
92+
public string Lastname { set; get; }
93+
94+
public NestedPerson Inner { set; get; }
95+
}
96+
#endregion

0 commit comments

Comments
 (0)