Я нахожусь в поиске написания TypedBinaryReader
, который мог бы читать любой тип, который обычно поддерживает BinaryReader, и тип, который реализует определенный интерфейс.Я подошел очень близко, но я еще не совсем там.
Для типов значений я сопоставил типы с функторами, которые вызывают соответствующие функции.
Для ссылочных типов, какПока они наследуют указанный мной интерфейс и могут быть сконструированы, функция ниже работает.
Однако я хочу создать универсальный универсальный вызов метода ReadUniversal<T>()
, который будет работать как для типов значений, так и для указанных выше.ссылочные типы.
Это попытка номер один, она работает, но она не является достаточно общей, мне все еще приходится заниматься делами.
public class TypedBinaryReader : BinaryReader {
private readonly Dictionary<Type, object> functorBindings;
public TypedBinaryReader(Stream input) : this(input, Encoding.UTF8, false) { }
public TypedBinaryReader(Stream input, Encoding encoding) : this(input, encoding, false) { }
public TypedBinaryReader(Stream input, Encoding encoding, bool leaveOpen) : base(input, encoding, leaveOpen) {
functorBindings = new Dictionary<Type, object>() {
{typeof(byte), new Func<byte>(ReadByte)},
{typeof(int), new Func<int>(ReadInt32)},
{typeof(short), new Func<short>(ReadInt16)},
{typeof(long), new Func<long>(ReadInt64)},
{typeof(sbyte), new Func<sbyte>(ReadSByte)},
{typeof(uint), new Func<uint>(ReadUInt32)},
{typeof(ushort), new Func<ushort>(ReadUInt16)},
{typeof(ulong), new Func<ulong>(ReadUInt64)},
{typeof(bool), new Func<bool>(ReadBoolean)},
{typeof(float), new Func<float>(ReadSingle)}
};
}
public T ReadValueType<T>() {
return ((Func<T>)functorBindings[typeof(T)])();
}
public T ReadReferenceType<T>() where T : MyReadableInterface, new() {
T item = new T();
item.Read(this);
return item;
}
public List<T> ReadMultipleValuesList<T, R>() {
dynamic size = ReadValueType<R>();
List<T> list = new List<T>(size);
for (dynamic i = 0; i < size; ++i) {
list.Add(ReadValueType<T>());
}
return list;
}
public List<T> ReadMultipleObjecsList<T, R>() where T : MyReadableInterface {
dynamic size = ReadValueType<R>();
List<T> list = new List<T>(size);
for (dynamic i = 0; i < size; ++i) {
list.Add(ReadReferenceType<T>());
}
return list;
}
}
Идея, которую я придумал, которую я не наденуна самом деле, это написать общий класс, который включает блоки в типах значений, как этот:
public class Value<T> : MyReadableInterface {
private T value;
public Value(T value) {
this.value = value;
}
internal Value(TypedBinaryReader reader) {
Read(reader);
}
public T Get() {
return value;
}
public void Set(T value) {
if (!this.value.Equals(value)) {
this.value = value;
}
}
public override string ToString() {
return value.ToString();
}
public void Read(TypedBinaryReader reader) {
value = reader.ReadValueType<T>();
}
}
Таким образом, я могу использовать ReadReferencTypes<T>()
даже для типов значений, пока я передаювведите параметр как Value<int>
вместо просто int
.
Но это по-прежнему ужасно, так как мне снова приходится вспоминать то, что я читаю, просто вместо того, чтобы запоминать сигнатуру функции, я должен помнитьфилиалx в типах значений.
Идеальным решением было бы добавление следующего метода к классу TypedBinaryReader
:
public T ReadUniversal<T>() {
if ((T).IsSubclassOf(typeof(MyReadableInterface)) {
return ReadReferenceType<T>();
} else if (functorBindings.ContainsKey(typeof(T)) {
return ReadValueType<T>();
} else {
throw new SomeException();
}
}
Однако из-за различных ограничений универсального аргумента T,это не сработает.Любые идеи о том, как заставить это работать?
Конечная цель состоит в том, чтобы прочитать любой тип, который обычно BinaryReader может или любой тип, который реализует интерфейс, используя только один метод.