Универсальный BinaryReader/запись чтение/запись методы


У меня есть расширение, которое реализует все BinaryReader/BinaryWriter в классе потока. Я хочу создать универсальные методы для них. Есть ли лучше способ сделать это?

public static void Write<T>(this Stream stream, T num)
{
    if (num is byte)
    {
        stream.Write((byte)(object)num);
    }
    else if (num is Int16)
    {
        stream.Write((Int16)(object)num);
    }
    else if (num is Int32)
    {
        stream.Write((Int32)(object)num);
    }
}

public static T Read<T>(this Stream stream)
{
    object ret = null;

    if (typeof(T) == typeof(byte))
        ret = stream.ReadInt8();
    else if (typeof(T) == typeof(Int16))
        ret = stream.ReadInt16();
    else if (typeof(T) == typeof(Int32))
        ret = stream.ReadInt32();

    if (ret == null)
        throw new ArgumentException("Unable to read type - " + typeof(T));
    return (T)ret;
}

Теперь, используя этот метод читайте.

static Dictionary<Type, Func<Stream, object>> ReadFuncs = new Dictionary<Type, Func<Stream, object>>()
{
    {typeof(bool), s => s.ReadBoolean()},
    {typeof(byte), s => s.ReadInt8()},
    {typeof(Int16), s => s.ReadInt16()},
    {typeof(Int32), s => s.ReadInt32()},
    {typeof(Int64), s => s.ReadInt64()},
    {typeof(string), s => s.ReadString()},
};
public static T Read<T>(this Stream stream)
{
    if (ReadFuncs.ContainsKey(typeof(T)))
        return (T)ReadFuncs[typeof(T)](stream);

    throw new NotImplementedException();
}


3228
5
c#
задан 28 марта 2011 в 11:03 Источник Поделиться
Комментарии
2 ответа

Я предполагаю, что вы определили пиши больше методов, чем это? В противном случае записать() назвали бы себя рекурсивно бесконечно. Вы, наверное, перегрузки для каждого поддерживаемого типа, делая общий метод записи ненадобностью. Это также объяснило бы странные формы, которую вы делаете. Я предполагаю, что перегруженная функция с определенным типом имеет более высокий приоритет, универсального метода, который является, почему это может сработать. Однако это не значит, что это чистое решение.

Ваш читать() метод, кажется, более полезным. Вместо того, чтобы бросать исключение ArgumentException я бы предпочел бросает исключение notsupportedexception.

К слову, вы уверены, что хотите сделать эти расширения методов трансляцию и не какой-то более конкретный поток? Трансляция может быть любого типа потока.


Каким образом это улучшение по сравнению с помощью BinaryWriter/BinaryReader? Для целей, как я понял из вашего кода, я бы только создать читать метод расширения для BinaryReader.

Если вы чувствуете, как экспериментировать немного, там, вероятно, будет более производительным/чище решение, хотя вы будете иметь, чтобы тест, чтобы быть уверенным. Вы могли бы создать словарь> провести сопоставление "читатель" для каждого типа. Инициализации делегатов магазине в этот словарь является жесткая часть, на которой информацию можно найти в этой статье. Скорее всего это не стоит усилий, хотя она все еще очень интересная статья. :) Не забудьте также проверить то же решение, выполненное с помощью деревьев выражений в комментариях к статье. Для реализации пример, который я сделал, проверить этот вопрос я выложил на ревью кода.

5
ответ дан 28 марта 2011 в 12:03 Источник Поделиться

Я знаю, что вы пытаетесь упростить код, но я думаю, что это будет лучше, чтобы пойти в противоположную сторону, во избежание родовых видах, а также делают специальные процедуры типа:

public static void WriteByte(this Stream stream, byte num) { ... }
public static void WriteInt16(this Stream stream, Int16 num) { ... }
public static void WriteInt32(this Stream stream, Int32 num) { ... }

Почему. Потому что его очень легко вызвать неправильный метод, называя "писать()" вместо "писать()". И в каком случае застройщик может не относиться к этим типам integer как же.

1
ответ дан 28 марта 2011 в 03:03 Источник Поделиться