Использование BinaryWriter в универсальном классе - PullRequest
0 голосов
/ 19 декабря 2018
[Serializable]
public class Vector3D<T> {
    public T x;
    public T y;
    public T z;
}

У меня есть этот простой класс Vector, который используется для хранения координат в различных числовых типах.

Мне нужно прочитать это из файла, а затем сохранить его.

Обычно онвыглядит примерно так:

someCoord = new Vector3D<int> {
                x = reader.ReadInt32(),
                y = reader.ReadInt32(),
                z = reader.ReadInt32()
            };
writer.Write(someCoord.x);
writer.Write(someCoord.y);
writer.Write(someCoord.z);

Я бы хотел превратить эти строки во что-то вроде этого:

someCoord = new Vector3D<int>(reader);
someCoord.Write(writer);

Я бы подготовил методы Read и Write в классе Vector3D.Хотя писать не проблема, так как я могу сделать что-то вроде:

writer.Write((T)x)

Попытка чтения таким же образом становится проблемой, так как мне приходится вызывать методы с разными именами, в зависимости от типа, который я хочучитай.

При всём, что говорится, есть ли какой-нибудь умный способ достичь этого?Я думал об использовании делегатов, но не могу понять синтаксис.

У меня был бы словарь, в котором я бы хранил пары Type-Function (делегат), чтобы, когда я захочу что-то прочитать,Я называю что-то вроде:

T value = reader.dictionary[T]();

, где reader - это экземпляр BinaryReader.Если T - это int, словарь [T] будет заменен на readInt32, если T будет float, словарь [T] будет заменен на readSingle и т. Д.

Есть идеи, как этого добиться?

1 Ответ

0 голосов
/ 19 декабря 2018

Вы можете создать универсальный метод, который опирается на универсальный тип <T>, обрабатывает чтение, упаковывает значение и, наконец, возвращает его.Например:

    public static Object GetValue<T>(BinaryReader br) {
        switch (Type.GetTypeCode(typeof(T)))
        {
            case TypeCode.Boolean: { return br.ReadBoolean(); }
            case TypeCode.Byte: { return br.ReadByte(); }
            case TypeCode.Char: { return br.ReadChar(); }
            case TypeCode.Decimal: { return br.ReadDecimal(); }
            case TypeCode.Double: { return br.ReadDouble(); }
            case TypeCode.Int16: { return br.ReadInt16(); }
            case TypeCode.Int32: { return br.ReadInt32(); }
            case TypeCode.Int64: { return br.ReadUInt64(); }
            // Keep on going for other types
            default: { return br.Read(); }
        }
    }

Вот полный пример

public class Vector3D<T>
{
    public T X { get; set; }
    public T Y { get; set; }
    public T Z { get; set; }
    private readonly String filePath;
    public Vector3D(String filePath) {
        this.filePath = filePath;
        if (File.Exists(filePath))
        {
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                using(BinaryReader br = new BinaryReader(fs))
                {
                    X = (T) GetValue<T>(br);
                    Y = (T) GetValue<T>(br);
                    Z = (T) GetValue<T>(br);
                }
            }
        }
    }

    public static Object GetValue<T>(BinaryReader br) {
        switch (Type.GetTypeCode(typeof(T)))
        {
            case TypeCode.Boolean: { return br.ReadBoolean(); }
            case TypeCode.Byte: { return br.ReadByte(); }
            case TypeCode.Char: { return br.ReadChar(); }
            case TypeCode.Decimal: { return br.ReadDecimal(); }
            case TypeCode.Double: { return br.ReadDouble(); }
            case TypeCode.Int16: { return br.ReadInt16(); }
            case TypeCode.Int32: { return br.ReadInt32(); }
            case TypeCode.Int64: { return br.ReadUInt64(); }
            default: { return br.Read(); }
        }
    }
}

Для этого также можно создать метод расширения:

public static class BinaryReaderExtensions
{
    public static Object GetValue(this BinaryReader br, Type type)
    {
        switch (Type.GetTypeCode(type))
        {
            case TypeCode.Boolean: { return br.ReadBoolean(); }
            case TypeCode.Byte: { return br.ReadByte(); }
            case TypeCode.Char: { return br.ReadChar(); }
            case TypeCode.Decimal: { return br.ReadDecimal(); }
            case TypeCode.Double: { return br.ReadDouble(); }
            case TypeCode.Int16: { return br.ReadInt16(); }
            case TypeCode.Int32: { return br.ReadInt32(); }
            case TypeCode.Int64: { return br.ReadUInt64(); }
            default: { return br.Read(); }
        }
    }
}

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...