I don't know why do you need this functionality(and if it is worth the hassle, taking in account that you are losing compile time safety) but you can try this to remove the unnecessary allocations in the solution by @Mike Zboray:
public static T Parse<T>(BinaryReader reader)
{
return ReaderProvider<T>.ReaderFunc(reader);
}
class ReaderProvider<T>
{
public static readonly Func<BinaryReader, T> ReaderFunc;
static ReaderProvider()
{
MethodInfo mi ;
if(typeof(T) == typeof(byte))
{
mi = typeof(BinaryReader).GetMethod(nameof(BinaryReader.ReadByte));
}
else if(typeof(T) == typeof(int))
{
mi = typeof(BinaryReader).GetMethod(nameof(BinaryReader.ReadInt32));
}
// ....
else
{
throw new ArgumentOutOfRangeException($"{typeof(T).FullName}");
}
var p = Expression.Parameter(typeof(BinaryReader));
ReaderFunc = Expression.Lambda<Func<BinaryReader, T>>(Expression.Call(p, mi), p).Compile();
}
}
Example usage:
var ms = new MemoryStream();
ms.Write(new byte[] { 1, 2, 0, 0, 0 }, 0, 5);
ms.Seek(0, SeekOrigin.Begin);
var x = new BinaryReader(ms);
Console.WriteLine(Parse<byte>(x));
Console.WriteLine(Parse<int>(x));
Also I highly recommend to stick with BinaryReader.ReadX
methods. If this is not suitable for then benchmark performance of both implementations.