Как использовать метод BinaryReader Read для чтения динамических данных?

Я пытаюсь использовать метод чтения 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?


person Monica    schedule 30.11.2012    source источник
comment
Для чего нужны звонки GetGenericTypeDefinition? Если T является универсальным типом, он точно не был создан ни из System.Int32, ни из System.String, потому что это не определения универсального типа. С другой стороны, если T является Int32 или String, GetGenericTypeDefinition выдаст InvalidOperationException, когда вы вызываете его для неуниверсальных типов.   -  person O. R. Mapper    schedule 30.11.2012
comment
Кроме того, это хороший пример того, как не использовать дженерики — перегрузки со всеми поддерживаемыми типами являются здесь лучшим решением, они делают всю ручную проверку типов с цепочкой ifs устаревшей.   -  person O. R. Mapper    schedule 30.11.2012


Ответы (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);
    }
}

Код, в котором вы вызываете это, будет чище, но вам все равно придется сопоставлять каждую функцию чтения с типом.

person Jon B    schedule 30.11.2012