public static Delegate GetReadMethodInfo <T>() { Type[] args = null; var typeOfT = typeof(T); if (typeOfT.IsDictionary() && (args = typeOfT.GetGenericArguments()) != null && args.Length == 2) { var metadataToken = unchecked (((ulong)(uint)args[0].MetadataToken << 32) | (ulong)(uint)args[1].MetadataToken); if (_readCache.TryGetValue(metadataToken, out var dstMethod)) { return(dstMethod); } else { var method = TypeSearcher.GetMethodsFromType(typeof(TBinaryExtendor), new Type[] { typeof(BinaryReader) }).FirstOrDefault(); dstMethod = method?.MakeGenericMethod(args).CreateDelegate(typeof(Func <BinaryReader, T>)); if (dstMethod != null) { _readCache[metadataToken] = dstMethod; return(dstMethod); } } } return(null); }
/// <summary> /// Static initializer; /// Basically searches for a method in the BinaryWriter/Reader class to automatically handle the given types /// </summary> static TBinaryAccessor() { var typeOfT = typeof(T); if (typeOfT == typeof(string)) { //Looks a bit ugly, but ¯\_(ツ)_/¯ //For reading: // 1.Read the len of the next string // 2.Read the amount of len of bytes and decode it to a string //For writing: // 1: Convert the given string to a byte[] // 2: Write the len of bytes in the array onto the stream // 3: Write the bytes onto the stream RegisterExtension(new Func <BinaryReader, string>(x => BaseEncoding.GetString(x.ReadBytes(x.ReadInt32()))) as Func <BinaryReader, T>, new Action <BinaryWriter, string>((m, x) => { var dstBytes = BaseEncoding.GetBytes(x); m.Write(dstBytes.Length); m.Write(dstBytes); }) as Action <BinaryWriter, T> ); } else if (typeOfT.IsPrimitive) { //Search for a method to read the given type var readMethodInfo = TypeSearcher.GetMethodsFromType(typeof(BinaryReader), new Type[0], typeOfT).FirstOrDefault(m => m.Name.StartsWith("Read") && m.Name != "Read"); if (readMethodInfo != null) { //Create a delegate, so that we don't have to use Methodinfo.Invoke which slows down the whole process _storReadFunc = (Func <BinaryReader, T>)readMethodInfo.CreateDelegate(typeof(Func <BinaryReader, T>)); } //Search for a method to write the given type onto a stream var writeMethodInfo = TypeSearcher.GetMethodsFromType(typeof(BinaryWriter), new Type[] { typeOfT }).FirstOrDefault(); if (writeMethodInfo != null) { _storWriteAct = (Action <BinaryWriter, T>)writeMethodInfo.CreateDelegate(typeof(Action <BinaryWriter, T>)); } } else { _storWriteAct = (bw, data) => { var serializer = (Func <T, byte[]>)MatroschkaResolve.GetWriteMethodInfo(data); if (serializer != null) { bw.Write(serializer(data)); } }; _storReadFunc = br => { var eval = (Func <BinaryReader, T>)MatroschkaResolve.GetReadMethodInfo <T>(); return(eval == null ? default(T) : eval(br)); }; } }