我在二进制反序列化器中使用了选项 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
};
另一种选择是让命令类自己进行序列化:
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;
}
但是这样你最终可能会复制一些代码。 (另一方面,派生类可以调用其父类版本的 Serialize/Deserialize,如果这在您的场景中有意义,并且效果很好。)