如何序列化包含接口类型属性的Person类?
解决接口类型属性的序列化问题
序列化包含接口类型属性的类时抛出System.NotSupportedException,是因为大多数序列化器无法直接处理接口——接口本身不能被实例化,序列化器需要明确知道要序列化的具体类型。以下是几种可行的解决办法:
1. 替换接口属性为具体实现类
直接把Person类中的INames类型属性改成具体的Names类,这是最简单直接的方案:
public class Person { public Names Names { get; set; } public double WeightKg { get; set; } public double HeightCm { get; set; } }
这样序列化器可以直接识别具体类型,无需额外配置。
2. 给序列化器指定接口的具体实现类型(以Json.NET为例)
如果必须保留接口类型,可以通过配置序列化器的类型信息来解决。比如使用Json.NET的TypeNameHandling,让序列化器在输出中添加类型标识:
序列化代码
var person = new Person { Names = new Names { First = "John", Last = "Doe" }, WeightKg = 70, HeightCm = 175 }; string json = JsonConvert.SerializeObject(person, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
反序列化代码
Person deserializedPerson = JsonConvert.DeserializeObject<Person>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
TypeNameHandling.Auto会自动在需要的地方(比如接口类型)添加类型信息,帮助序列化器识别具体实现类。
3. 使用DataContractSerializer并声明已知类型
如果使用WCF的DataContractSerializer,可以通过[KnownType]特性告诉序列化器接口对应的具体实现类:
[DataContract] [KnownType(typeof(Names))] public class Person { [DataMember] public INames Names { get; set; } [DataMember] public double WeightKg { get; set; } [DataMember] public double HeightCm { get; set; } } [DataContract] public class Names : INames { [DataMember] public string First { get; set; } [DataMember] public string Last { get; set; } } public interface INames { string First { get; set; } string Last { get; set; } }
[KnownType(typeof(Names))]标记告诉序列化器,处理INames类型时可以接受Names类的实例。
4. 自定义序列化逻辑
如果以上方案都不适用,可以手动实现序列化逻辑。比如针对BinaryFormatter实现ISerializable接口:
[Serializable] public class Person : ISerializable { public INames Names { get; set; } public double WeightKg { get; set; } public double HeightCm { get; set; } public Person() { } protected Person(SerializationInfo info, StreamingContext context) { // 反序列化时直接读取具体类型 Names = (Names)info.GetValue("Names", typeof(Names)); WeightKg = info.GetDouble("WeightKg"); HeightCm = info.GetDouble("HeightCm"); } public void GetObjectData(SerializationInfo info, StreamingContext context) { // 序列化时将接口属性当作具体类型写入 info.AddValue("Names", Names, typeof(Names)); info.AddValue("WeightKg", WeightKg); info.AddValue("HeightCm", HeightCm); } }
通过手动控制序列化和反序列化的过程,强制将接口类型转换为具体实现类处理。
内容的提问来源于stack exchange,提问作者user98
相关产品推荐
相关产品推荐

