Skip to content

Commit ba37a8f

Browse files
committed
Added a description and examples of using custom converters.
Added UnutTest custom converter.
1 parent 1db9d0c commit ba37a8f

File tree

6 files changed

+332
-1
lines changed

6 files changed

+332
-1
lines changed

README.md

Lines changed: 209 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,215 @@ var result = (TestClass)MessagePackSerializer.Deserialize(typeof(TestClass), byt
3535

3636
### Your type serialization/deserialization
3737

38-
If you want to work with your own types, first thing you need to add is a type converter.
38+
If you want to work with your own types, first thing you need to add is a type converter. Although the library provides almost complete coverage of the serialization/deserialization of any objects, there are certain cases where it is difficult to do without a custom converter.
39+
40+
#### The general principle of implementing a custom converter
41+
42+
1) In the code of your project, you need to create a converter class that inherits the IConverter interface and implement the Read and Write interface methods:
43+
44+
```csharp
45+
public class SimpleCustomConverter : IConverter
46+
{
47+
#nullable enable
48+
public void Write(object? value, [NotNull] IMessagePackWriter writer)
49+
{
50+
//TODO Your code is here
51+
}
52+
53+
public object? Read([NotNull] IMessagePackReader reader)
54+
{
55+
var yourObject = new YourObject();
56+
//TODO Your code is here
57+
return yourObject;
58+
}
59+
}
60+
```
61+
62+
2) Register your custom converter in the context of serialization:
63+
64+
```csharp
65+
public class Program
66+
{
67+
public static void Main()
68+
{
69+
var simpleCustomConverter = new SimpleCustomConverter();
70+
ConverterContext.Add(typeof(YourObject), simpleCustomConverter);
71+
}
72+
}
73+
```
74+
75+
After completing these steps, the serialization/deserialization of the object for which your converter is added will occur in the methods of the custom converter.
76+
77+
##### A few examples of the implementation of custom converters
78+
79+
1. Case with enumeration elements as strings:
80+
81+
```csharp
82+
namespace samples
83+
{
84+
public enum FieldType
85+
{
86+
_ = -1,
87+
Str,
88+
Num,
89+
Any
90+
}
91+
92+
public class FieldTypeConverter : IConverter
93+
{
94+
internal FieldType Read(IMessagePackReader reader)
95+
{
96+
var stringConverter = ConverterContext.GetConverter(typeof(string));
97+
98+
var enumString = (string)stringConverter.Read(reader);
99+
100+
return enumString switch
101+
{
102+
"Str" => FieldType.Str,
103+
"Num" => FieldType.Num,
104+
"*" => FieldType.Any,
105+
_ => throw new Exception($"Unexpected enum {typeof(FieldType)} underlying type: {enumString}"),
106+
};
107+
}
108+
109+
internal void Write(FieldType value, [NotNull] IMessagePackWriter writer)
110+
{
111+
var stringConverter = ConverterContext.GetConverter(typeof(string));
112+
113+
switch (value)
114+
{
115+
case FieldType.Str:
116+
stringConverter.Write("Str", writer);
117+
break;
118+
case FieldType.Num:
119+
stringConverter.Write("Num", writer);
120+
break;
121+
case FieldType.Any:
122+
stringConverter.Write("*", writer);
123+
break;
124+
default:
125+
throw new Exception($"Enum {value.GetType()} value: {value} expected");
126+
}
127+
}
128+
129+
#nullable enable
130+
object? IConverter.Read([NotNull] IMessagePackReader reader)
131+
{
132+
return Read(reader);
133+
}
134+
135+
public void Write(object? value, [NotNull] IMessagePackWriter writer)
136+
{
137+
Write((FieldType)value!, writer);
138+
}
139+
}
140+
}
141+
```
142+
143+
2. Case compression or concealment of transmitted strings between sender and recipient if sender and recipient share the same vocabulary of words:
144+
145+
```csharp
146+
namespace samples
147+
{
148+
public static class SharedWordDictionary
149+
{
150+
static SharedWordDictionary()
151+
{
152+
WordDictionary = new ArrayList
153+
{
154+
"MessagePak",
155+
"Hello",
156+
"at",
157+
"nanoFramework!",
158+
" "
159+
};
160+
}
161+
162+
public static ArrayList WordDictionary { get; }
163+
}
164+
165+
public class SecureMessage
166+
{
167+
public SecureMessage(string message)
168+
{
169+
Message = message;
170+
}
171+
172+
public string Message { get; private set; }
173+
}
174+
175+
public class SecureMessageConverter : IConverter
176+
{
177+
public SecureMessage Read([NotNull] IMessagePackReader reader)
178+
{
179+
StringBuilder sb = new();
180+
var length = reader.ReadArrayLength();
181+
182+
for(int i = 0; i < length; i++)
183+
{
184+
sb.Append(SharedWordDictionary.WordDictionary[i]);
185+
sb.Append(' ');
186+
}
187+
if (sb.Length > 0)
188+
sb.Remove(sb.Length - 1, 1);
189+
190+
return new SecureMessage(sb.ToString());
191+
}
192+
193+
public void Write(SecureMessage value, [NotNull] IMessagePackWriter writer)
194+
{
195+
var messageWords = value.Message.Split(' ');
196+
197+
uint length = BitConverter.ToUInt32(BitConverter.GetBytes(messageWords.Length), 0);
198+
writer.WriteArrayHeader(length);
199+
200+
var intConverter = ConverterContext.GetConverter(typeof(int));
201+
202+
foreach (var word in messageWords)
203+
{
204+
intConverter.Write(SharedWordDictionary.WordDictionary.IndexOf(word), writer);
205+
}
206+
}
207+
208+
#nullable enable
209+
object? IConverter.Read([NotNull] IMessagePackReader reader)
210+
{
211+
return Read(reader);
212+
}
213+
214+
public void Write(object? value, [NotNull] IMessagePackWriter writer)
215+
{
216+
Write((SecureMessage)value!, writer);
217+
}
218+
}
219+
220+
public class Program
221+
{
222+
public static void Main()
223+
{
224+
var secureMessageConverter = new SecureMessageConverter();
225+
ConverterContext.Add(typeof(SecureMessage), secureMessageConverter);
226+
227+
var secureMessage = new SecureMessage("Hello MessagePack at nanoFramework!");
228+
229+
//At sender
230+
var buffer = MessagePackSerializer.Serialize(secureMessage);
231+
Debug.WriteLine($"The message:\n{secureMessage.Message}\nbeing sent has been serialized into {buffer.Length} bytes.");
232+
//and sent to recipient
233+
//
234+
//..........................
235+
Debug.WriteLine("=============================================");
236+
237+
//At recipient, after receiving the byte array
238+
Debug.WriteLine($"Received {buffer.Length} bytes");
239+
240+
var recipientSecureMessage = (SecureMessage)MessagePackSerializer.Deserialize(typeof(SecureMessage), buffer)!;
241+
242+
Debug.WriteLine($"Message received:\n{recipientSecureMessage.Message}");
243+
}
244+
}
245+
}
246+
```
39247

40248
## Acknowledgements
41249

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace UnitTestShared.TestData
5+
{
6+
public class SecureMessage
7+
{
8+
public SecureMessage(string message)
9+
{
10+
Message = message;
11+
}
12+
13+
public string Message { get; private set; }
14+
}
15+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics.CodeAnalysis;
5+
using System.Text;
6+
using nanoFramework.MessagePack;
7+
using nanoFramework.MessagePack.Converters;
8+
using nanoFramework.MessagePack.Stream;
9+
using System;
10+
11+
namespace UnitTestShared.TestData
12+
{
13+
public class SecureMessageConverter : IConverter
14+
{
15+
public SecureMessage Read([NotNull] IMessagePackReader reader)
16+
{
17+
StringBuilder sb = new();
18+
var length = reader.ReadArrayLength();
19+
20+
for (int i = 0; i < length; i++)
21+
{
22+
sb.Append(SharedWordDictionary.WordDictionary[i]);
23+
sb.Append(' ');
24+
}
25+
if (sb.Length > 0)
26+
sb.Remove(sb.Length - 1, 1);
27+
28+
return new SecureMessage(sb.ToString());
29+
}
30+
31+
public void Write(SecureMessage value, [NotNull] IMessagePackWriter writer)
32+
{
33+
var messageWords = value.Message.Split(' ');
34+
35+
uint length = BitConverter.ToUInt32(BitConverter.GetBytes(messageWords.Length), 0);
36+
writer.WriteArrayHeader(length);
37+
38+
var intConverter = ConverterContext.GetConverter(typeof(int));
39+
40+
foreach (var word in messageWords)
41+
{
42+
intConverter.Write(SharedWordDictionary.WordDictionary.IndexOf(word), writer);
43+
}
44+
}
45+
46+
#nullable enable
47+
object? IConverter.Read([NotNull] IMessagePackReader reader)
48+
{
49+
return Read(reader);
50+
}
51+
52+
public void Write(object? value, [NotNull] IMessagePackWriter writer)
53+
{
54+
Write((SecureMessage)value!, writer);
55+
}
56+
}
57+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Collections;
5+
6+
namespace UnitTestShared.TestData
7+
{
8+
public static class SharedWordDictionary
9+
{
10+
static SharedWordDictionary()
11+
{
12+
WordDictionary = new()
13+
{
14+
"MessagePak",
15+
"Hello",
16+
"at",
17+
"nanoFramework!",
18+
" "
19+
};
20+
}
21+
22+
public static ArrayList WordDictionary { get; }
23+
}
24+
}

UnitTestShared/UnitTestShared.projitems

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
<Import_RootNamespace>UnitTestShared</Import_RootNamespace>
1010
</PropertyGroup>
1111
<ItemGroup>
12+
<Compile Include="$(MSBuildThisFileDirectory)TestData\SecureMessage.cs" />
13+
<Compile Include="$(MSBuildThisFileDirectory)TestData\SecureMessageConverter.cs" />
14+
<Compile Include="$(MSBuildThisFileDirectory)TestData\SharedWordDictionary.cs" />
1215
<Compile Include="$(MSBuildThisFileDirectory)TestData\TestConverter.cs" />
1316
<Compile Include="$(MSBuildThisFileDirectory)TestData\TestClass.cs" />
1417
<Compile Include="$(MSBuildThisFileDirectory)Helpers\TestsHelper.cs" />

UnitTestShared/UnitTests.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,30 @@ public void ProcessCustomObjectTest()
117117

118118
Assert.AreEqual(test, testResult);
119119
}
120+
121+
[TestMethod]
122+
public void CustomConverterTest()
123+
{
124+
var secureMessageConverter = new SecureMessageConverter();
125+
ConverterContext.Add(typeof(SecureMessage), secureMessageConverter);
126+
127+
var secureMessage = new SecureMessage("Hello MessagePack at nanoFramework!");
128+
129+
//At sender
130+
var buffer = MessagePackSerializer.Serialize(secureMessage);
131+
Debug.WriteLine($"The message:\n{secureMessage.Message}\nbeing sent has been serialized into {buffer.Length} bytes.");
132+
//and sent to recipient
133+
//
134+
//..........................
135+
Debug.WriteLine("=============================================");
136+
137+
//At recipient, after receiving the byte array
138+
Debug.WriteLine($"Received {buffer.Length} bytes");
139+
140+
var recipientSecureMessage = (SecureMessage)MessagePackSerializer.Deserialize(typeof(SecureMessage), buffer)!;
141+
142+
Debug.WriteLine($"Message received:\n{recipientSecureMessage.Message}");
143+
}
120144
}
121145

122146

0 commit comments

Comments
 (0)