And*_*per 6 .net c# binary deserialization
我正在编写二进制序列化器/ deserialser来将许多对象类型转换为字节流.对象表示通过蓝牙或USB连接的设备的API命令及其相关响应.我正在使用BinaryWriter&BinaryReader来写入/读取流.
序列化器很简单.要序列化的特性标记有一个属性,该属性指定将它们写入字节流的顺序.我使用反射和重载分辨率句柄迭代属性,选择正确的Write(...)方法BinaryWriter.
解串器并不那么简单.我再次可以遍历特定响应类中的特性,我期望确定需要从流中读取的类型.棘手的一点就是选择正确的方法调用BinaryReader来读取我需要的值.我想到了两种方法.
ReadXXXX()根据要读取的类型调用正确的方法.我有没有想到更简单的方法?根据您想要的返回类型,您无法进行重载解析,这简直太遗憾了.
我在二进制反序列化器中使用了选项 1(大 switch 语句)。更干净的方法可能是这样的:
{
object result;
BinaryReader ...;
foreach (var propertyInfo in ...)
{
Func<BinaryReader, object> deserializer;
if (!supportedTypes.TryGetValue(propertyInfo.PropertyType, out deserializer))
{
throw new NotSupportedException(string.Format(
"Type of property '{0}' isn't supported ({1}).", propertyInfo.Name, propertyInfo.PropertyType));
}
var deserialized = deserializer(reader);
propertyInfo.SetValue(result, deserialized, null);
}
}
private static Dictionary<Type, Func<BinaryReader, object>> supportedTypes = new Dictionary<Type, Func<BinaryReader, object>>
{
{ typeof(int), br => br.ReadInt32() },
// etc
};
Run Code Online (Sandbox Code Playgroud)
另一种选择是让命令类本身进行序列化:
interface IBinarySerializable
{
void Serialize(BinaryWriter toStream);
void Deserialize(BinaryReader fromStream);
}
Run Code Online (Sandbox Code Playgroud)
然后在你的命令中:
abstract class Command : IBinarySerializable
{
}
class SomeCommand : Command
{
public int Arg1 { get; set; }
public void Serialize(BinaryWriter toStream)
{
toStream.Write(Arg1);
}
public void Deserialize(BinaryReader fromStream)
{
Arg1 = fromStream.ReadInt32();
}
}
Run Code Online (Sandbox Code Playgroud)
以及通用序列化方法:
void Serialize<T>(T obj) where T : IBinarySerializable
{
obj.Serialize(_stream);
}
T Deserialize<T>() where T : new(), IBinarySerializable
{
var result = new T();
result.Deserialize(_stream);
return result;
}
Run Code Online (Sandbox Code Playgroud)
但这样你可能最终会重复一些代码。(另一方面,如果这在您的场景中有意义,则派生类可以调用其父类版本的序列化/反序列化,并且效果很好。)
| 归档时间: |
|
| 查看次数: |
2917 次 |
| 最近记录: |