I'm trying to use a BinaryReader Read method in a generic way. Only at run time I know the type of data being read.
public static T ReadData<T>(string fileName)
{
var value = default(T);
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (var reader = new BinaryReader(fs))
{
if (typeof (T).GetGenericTypeDefinition() == typeof (Int32))
{
value = (dynamic) reader.ReadInt32();
}
if (typeof (T).GetGenericTypeDefinition() == typeof (string))
{
value = (dynamic) reader.ReadString();
}
// More if statements here for other type of data
}
}
return value ;
}
How can I avoid the multiple if statements?
Other than using reflection (which would be slow), the only option I can think of that you might like better would be to build a dictionary:
static object s_lock = new object();
static IDictionary<Type, Func<BinaryReader, dynamic>> s_readers = null;
static T ReadData<T>(string fileName)
{
lock (s_lock)
{
if (s_readers == null)
{
s_readers = new Dictionary<Type, Func<BinaryReader, dynamic>>();
s_readers.Add(typeof(int), r => r.ReadInt32());
s_readers.Add(typeof(string), r => r.ReadString());
// Add more here
}
}
if (!s_readers.ContainsKey(typeof(T))) throw new ArgumentException("Invalid type");
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var reader = new BinaryReader(fs))
{
return s_readers[typeof(T)](reader);
}
}
The code where you call this will be cleaner, but you're still stuck having to map each Read function to a type.