Last active
April 23, 2018 16:19
-
-
Save reniris/78eeb527e6a9a9c111ad760b2a439075 to your computer and use it in GitHub Desktop.
ReactivePropertySlimResolver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Reactive; | |
using System.Reflection; | |
using System.Text; | |
using MessagePack.Formatters; | |
using Reactive.Bindings; | |
namespace MessagePack.ReactivePropertyExtension | |
{ | |
public class ReactivePropertySlimResolver : IFormatterResolver | |
{ | |
public static IFormatterResolver Instance = new ReactivePropertySlimResolver(); | |
ReactivePropertySlimResolver() | |
{ | |
} | |
public IMessagePackFormatter<T> GetFormatter<T>() | |
{ | |
return FormatterCache<T>.formatter; | |
} | |
static class FormatterCache<T> | |
{ | |
public static readonly IMessagePackFormatter<T> formatter; | |
static FormatterCache() | |
{ | |
formatter = (IMessagePackFormatter<T>)ReactivePropertySlimResolverGetFormatterHelper.GetFormatter(typeof(T)); | |
} | |
} | |
} | |
internal static class ReactivePropertySlimResolverGetFormatterHelper | |
{ | |
static readonly Dictionary<Type, Type> formatterMap = new Dictionary<Type, Type>() | |
{ | |
{typeof(ReactivePropertySlim<>), typeof(ReactivePropertySlimFormatter<>)}, | |
}; | |
internal static object GetFormatter(Type t) | |
{ | |
var ti = t.GetTypeInfo(); | |
if (ti.IsGenericType) | |
{ | |
var genericType = ti.GetGenericTypeDefinition(); | |
if (formatterMap.TryGetValue(genericType, out Type formatterType)) | |
{ | |
return CreateInstance(formatterType, ti.GenericTypeArguments); | |
} | |
} | |
return null; | |
} | |
static object CreateInstance(Type genericType, Type[] genericTypeArguments, params object[] arguments) | |
{ | |
return Activator.CreateInstance(genericType.MakeGenericType(genericTypeArguments), arguments); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using MessagePack.Formatters; | |
using Reactive.Bindings; | |
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
namespace MessagePack.ReactivePropertyExtension | |
{ | |
// [Mode, Value] | |
public class ReactivePropertySlimFormatter<T> : IMessagePackFormatter<ReactivePropertySlim<T>> | |
{ | |
public int Serialize(ref byte[] bytes, int offset, ReactivePropertySlim<T> value, IFormatterResolver formatterResolver) | |
{ | |
if (value == null) | |
{ | |
return MessagePackBinary.WriteNil(ref bytes, offset); | |
} | |
else | |
{ | |
var startOffset = offset; | |
offset += MessagePackBinary.WriteFixedArrayHeaderUnsafe(ref bytes, offset, 2); | |
offset += MessagePackBinary.WriteInt32(ref bytes, offset, ReactivePropertySlimModeMapper.ToReactivePropertySlimModeInt(value)); | |
offset += formatterResolver.GetFormatterWithVerify<T>().Serialize(ref bytes, offset, value.Value, formatterResolver); | |
return offset - startOffset; | |
} | |
} | |
public ReactivePropertySlim<T> Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) | |
{ | |
if (MessagePackBinary.IsNil(bytes, offset)) | |
{ | |
readSize = 1; | |
return null; | |
} | |
else | |
{ | |
var startOffset = offset; | |
var length = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); | |
offset += readSize; | |
if (length != 2) throw new InvalidOperationException("Invalid ReactivePropertySlim data."); | |
var mode = (ReactivePropertyMode)MessagePackBinary.ReadInt32(bytes, offset, out readSize); | |
offset += readSize; | |
var v = formatterResolver.GetFormatterWithVerify<T>().Deserialize(bytes, offset, formatterResolver, out readSize); | |
offset += readSize; | |
readSize = offset - startOffset; | |
return new ReactivePropertySlim<T>(v, mode); | |
} | |
} | |
} | |
public static class ReactivePropertySlimModeMapper | |
{ | |
internal static int ToReactivePropertySlimModeInt<T>(global::Reactive.Bindings.ReactivePropertySlim<T> reactiveProperty) | |
{ | |
var mode = ReactivePropertyMode.None; | |
if (reactiveProperty.IsDistinctUntilChanged) | |
{ | |
mode |= ReactivePropertyMode.DistinctUntilChanged; | |
} | |
if (reactiveProperty.IsRaiseLatestValueOnSubscribe) | |
{ | |
mode |= ReactivePropertyMode.RaiseLatestValueOnSubscribe; | |
} | |
return (int)mode; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment