2012-11-30 43 views
3

我想以通用的方式使用BinaryReader读取方法。只有在运行时我知道正在读取的数据的类型。如何使用BinaryReader读取方法读取动态数据?

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 ; 
     } 

如何避免多个if语句?

+0

那里调用'GetGenericTypeDefinition'的是什么?如果'T'是一个泛型类型,它肯定不是由'System.Int32'或'System.String'构造的,因为它们不是泛型类型定义。另一方面,如果'T' *是*'Int32'或'String','GetGenericTypeDefinition'将在非泛型类型上调用''InvalidOperationException''。 –

+0

此外,这是如何*不*使用泛型的一个很好的例子 - 所有类型支持的重载是一个更好的解决方案,他们使所有手动类型检查与链接'if's过时。 –

回答

1

除了使用反射(这将是缓慢的),我能想到的唯一的选择,你可能更喜欢将构建一个字典:

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); 
    } 
} 

,你叫这将是更清洁的代码,但是你仍然不得不将每个Read函数映射到一个类型。

+0

谢谢,我认为这会让我的代码更清洁。 – Monica