我在尝试在 .net 标准 2.0 中进行二进制序列化时遇到了这个问题。我最终使用自定义SurrogateSelector
和SerializationBinder
.
是必需的TypeSerializationBinder
,因为框架System.RuntimeType
在获得SurrogateSelector
. 我真的不明白为什么必须在此步骤之前解析类型...
这是代码:
// Serializes and deserializes System.Type
public class TypeSerializationSurrogate : ISerializationSurrogate {
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) {
info.AddValue(nameof(Type.FullName), (obj as Type).FullName);
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) {
return Type.GetType(info.GetString(nameof(Type.FullName)));
}
}
// Just a stub, doesn't need an implementation
public class TypeStub : Type { ... }
// Binds "System.RuntimeType" to our TypeStub
public class TypeSerializationBinder : SerializationBinder {
public override Type BindToType(string assemblyName, string typeName) {
if(typeName == "System.RuntimeType") {
return typeof(TypeStub);
}
return Type.GetType($"{typeName}, {assemblyName}");
}
}
// Selected out TypeSerializationSurrogate when [de]serializing Type
public class TypeSurrogateSelector : ISurrogateSelector {
public virtual void ChainSelector(ISurrogateSelector selector) => throw new NotSupportedException();
public virtual ISurrogateSelector GetNextSelector() => throw new NotSupportedException();
public virtual ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector) {
if(typeof(Type).IsAssignableFrom(type)) {
selector = this;
return new TypeSerializationSurrogate();
}
selector = null;
return null;
}
}
使用示例:
byte[] bytes
var serializeFormatter = new BinaryFormatter() {
SurrogateSelector = new TypeSurrogateSelector()
}
using (var stream = new MemoryStream()) {
serializeFormatter.Serialize(stream, typeof(string));
bytes = stream.ToArray();
}
var deserializeFormatter = new BinaryFormatter() {
SurrogateSelector = new TypeSurrogateSelector(),
Binder = new TypeDeserializationBinder()
}
using (var stream = new MemoryStream(bytes)) {
type = (Type)deserializeFormatter .Deserialize(stream);
Assert.Equal(typeof(string), type);
}