Last active
July 25, 2019 15:09
-
-
Save sitepodmatt/99480607962e2bf9de092e84890dd693 to your computer and use it in GitHub Desktop.
fsharp union codec
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
public static class FSharpUnionCodecBuilder | |
{ | |
public delegate T Decoder<T>(byte[] bytes, string subType); | |
public delegate byte[] Encoder<T>(T input); | |
public static Tuple<Decoder<T>,Encoder<T>> Build<T>(T unionType) where T : class | |
{ | |
var unionCaseFields = FSharpType.GetUnionCases(typeof(T), BindingFlags.Public) | |
.ToDictionary(uc => $"{uc.DeclaringType.Name}:{uc.Name}", | |
uc => new Tuple<UnionCaseInfo, Type>(uc, | |
uc.GetFields().FirstOrDefault()?.DeclaringType | |
?? throw new ArgumentException("Must have union case argument"))); | |
var decoder = (Decoder<T>) ((byte[] bytes, string subTypeName) => { | |
var jsonText = System.Text.Encoding.UTF8.GetString(bytes); | |
var (targetSubType, fieldType) = | |
unionCaseFields[subTypeName] ?? throw new ArgumentException("Valid subtype expected"); | |
var subInstance = JsonConvert.DeserializeObject(jsonText, fieldType); | |
var wrapped = FSharpValue.MakeUnion(targetSubType, new [] { fieldType }, null); | |
return (T) wrapped; | |
}); | |
Encoder<T> encoder = null; //TODO | |
return new Tuple<Decoder<T>, Encoder<T>>(decoder, encoder); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment