我正在编写二进制序列化/反序列化器,以将许多对象类型转换为/从字节流。对象表示通过蓝牙或USB连接的设备的API命令及其相关响应。我使用BinaryWriter & BinaryReader对流进行写入/读取。
连载很简单。要序列化的属性被标记为一个属性,该属性指定要写入字节流的顺序。我使用反射和重载解析来迭代属性,选择BinaryWriter的正确的BinaryWriter方法。
去列器并不是那么简单。同样,我可以迭代特定响应类中的属性,以确定需要从流中读取的类型。棘手之处在于选择正确的方法来调用BinaryReader来读取我需要的值。我想过两种方法。
ReadXXXX()方法。调用该方法。
有没有更简单的方法让我不去想?遗憾的是,您不能根据所需的返回类型执行重载解析。
发布于 2012-03-27 04:14:40
我在二进制反序列化器中使用了选项1(大开关语句)。一个更干净的方法可以是这样的:
{
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
};另一种选择是让命令类自己执行序列化:
interface IBinarySerializable
{
void Serialize(BinaryWriter toStream);
void Deserialize(BinaryReader fromStream);
}然后在你的命令中:
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();
}
}和通用序列化方法:
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;
}但这样你可能会复制一些代码。(另一方面,派生类可以调用它们的父类版本的序列化/反序列化,如果这在您的场景中是有意义的,并且工作得很好。)
发布于 2012-03-27 12:07:50
我不知道我是否完全明白你想做什么。但是,听起来您应该更仔细地查看BinaryFormatter及其在.NET中的序列化代理。BinaryFormatter允许您轻松地序列化和反序列化对象,序列化代理允许您添加自定义序列化和反序列化逻辑,还可以将一个对象重构到antoher。
请看这里:
BinaryFormatter http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx
ISerializationSurrogate http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializationsurrogate.aspx
SurrogateSelector http://msdn.microsoft.com/en-us/library/system.runtime.serialization.surrogateselector.aspx
SerializationBinder http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationbinder.aspx
这里还可以看到一个小示例,其中我有一个方法可以将任何对象序列化为一个base64编码的字符串,然后是一个反序列化方法,它可以反序列化这个字符串。我还向格式化程序中添加了一个SerializationBinder,该格式化程序将类型MyOldClass的序列化重命名为MyNewClass类型,并且还添加了一个自定义ISerializationSurrogate,该ISerializationSurrogate可以在将其添加到ner类之前处理对象中字段的值。
public class SerializeDeserializeExample {
public string Serialize(object objectToSerialize) {
using(var stream = new MemoryStream()) {
new BinaryFormatter().Serialize(stream, objectToSerialize);
return Convert.ToBase64String(stream.ToArray());
}
}
public object Deserialize(string base64String) {
using(var stream = new MemoryStream(Convert.FromBase64String(base64String))) {
var formatter = new BinaryFormatter();
var surrogateSelector = new SurrogateSelector();
formatter.SurrogateSelector = surrogateSelector;
formatter.Binder = new DeserializationBinder(surrogateSelector);
return formatter.Deserialize(stream);
}
}
}
public class MyDeserializationBinder : SerializationBinder {
private readonly SurrogateSelector surrogateSelector;
public MyDeserializationBinder(SurrogateSelector surrogateSelector) {
this.surrogateSelector = surrogateSelector;
}
public override Type BindToType(string assemblyName, string typeName) {
if(typeName.Equals("MyOldClass", StringComparison.InvariantCultureIgnoreCase)) {
return RemapToType();
}
return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
}
private Type RemapToType() {
var remapToType = typeof(MyNewClass);
surrogateSelector.AddSurrogate(remapToType,
new StreamingContext(StreamingContextStates.All),
new MyCustomDeserializationSurrogate());
return remapToType;
}
}
public sealed class MyCustomDeserializationSurrogate : ISerializationSurrogate {
public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context) {
throw new NotImplementedException();
}
public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) {
var objectType = obj.GetType();
var fields = GetFields(objectType);
foreach(var fieldInfo in fields) {
var fieldValue = info.GetValue(fieldInfo.Name, fieldInfo.FieldType);
fieldValue = DoSomeProcessing(fieldValue);
fieldInfo.SetValue(obj, fieldValue);
}
return obj;
}
private static IEnumerable<FieldInfo> GetFields(Type objectType) {
return objectType.GetFields(BindingFlags.Instance | BindingFlags.DeclaredOnly |
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
private static object DoSomeProcessing(object value){
//Do some processing with the object
}
}https://stackoverflow.com/questions/9883139
复制相似问题