Can I serialize a C# Type object?

前端 未结 6 1544
南方客
南方客 2020-12-04 17:18

I\'m trying to serialize a Type object in the following way:

Type myType = typeof (StringBuilder);
var serializer = new XmlSerializer(typeof(Type));
TextWrit         


        
6条回答
  •  攒了一身酷
    2020-12-04 18:07

    I came across this issue trying to do binary serialization in .net standard 2.0. I ended up solving the problem using a custom SurrogateSelector and SerializationBinder.

    The TypeSerializationBinder was required because the framework was having trouble resolving System.RuntimeType before it got SurrogateSelector. I don't really understand why the type must be resolved before this step though...

    Here is the code:

    // 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;
        }
    }
    

    Usage Example:

    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);
    }
    

提交回复
热议问题