Skip to content

Instantly share code, notes, and snippets.

@skipme
Last active November 12, 2019 21:02
Show Gist options
  • Save skipme/6ed63ea3d1713139d20be8daebbc3ad1 to your computer and use it in GitHub Desktop.
Save skipme/6ed63ea3d1713139d20be8daebbc3ad1 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using MessagePack;
using MessagePack.Formatters;
namespace castt
{
public class WithString
{
public string X { get; set; }
}
public class WithInt
{
public int X { get; set; }
}
class Program
{
static void Main(string[] args)
{
var z = MessagePack.MessagePackSerializer.Serialize(new WithInt() { X = 4444 }, MessagePack.MessagePackSerializerOptions.Standard.WithResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance));
var s = MessagePack.MessagePackSerializer.Deserialize<WithString>(z, MessagePack.MessagePackSerializerOptions.Standard.WithResolver(MessagePack.Resolvers.CompositeResolver.Create(SampleCustomResolver.Instance, MessagePack.Resolvers.ContractlessStandardResolver.Instance)));
Console.WriteLine("Hello World!");
}
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(string), new NullableStringFormatter()}
// 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;
}
}
public sealed class NullableStringFormatter : IMessagePackFormatter<String>
{
public static readonly NullableStringFormatter Instance = new NullableStringFormatter();
public NullableStringFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, string value, MessagePackSerializerOptions options)
{
writer.Write(value);
}
public string Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.NextMessagePackType == MessagePackType.String)
return reader.ReadString();
return PrimitiveObjectFormatter.Instance.Deserialize(ref reader, options)?.ToString();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment