跨应用序列化异常:控制台无法反序列化PerfisDeAcesso数组属性
解决跨应用反序列化数组属性的报错问题
这个问题我之前在做跨应用数据同步的时候也碰到过!核心原因要么是领域类的程序集标识不一致,要么是序列化/反序列化的配置不统一,给你几个针对性的解决思路:
一、最推荐:把领域模型抽成共享类库
你现在网站和控制台里的Comunicado、PerfilDeAcesso是各自实现的,哪怕代码完全一样,它们在CLR里也是两个不同的类型(因为属于不同的程序集)。序列化的时候会把类型的程序集信息写入到数据里,控制台反序列化时找不到对应程序集的类型,就会报这个错。
解决办法很简单:
- 新建一个类库项目(比如叫
YourProject.Domain),把所有领域类(包括Comunicado、PerfilDeAcesso)移到这个类库里 - 网站和控制台项目都引用这个类库
这样两个应用里使用的是同一个程序集的同一种类型,序列化和反序列化时类型标识完全匹配,从根源上解决问题,还能避免重复代码。
二、临时方案:调整序列化配置忽略程序集信息
如果暂时没法重构到共享类库,可以修改序列化器的配置,让它不写入程序集信息,或者反序列化时忽略程序集差异。
如果你用的是Newtonsoft.Json:
网站端(序列化时):
var jsonSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None, // 不写入类型的程序集信息 Formatting = Formatting.Indented }; string serializedData = JsonConvert.SerializeObject(yourComunicadoInstance, jsonSettings);
控制台端(反序列化时):
var jsonSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None, // 如果还是有问题,用自定义Binder映射类型 SerializationBinder = new CrossAppSerializationBinder() }; var comunicado = JsonConvert.DeserializeObject<Comunicado>(serializedData, jsonSettings);
自定义Binder的实现:
public class CrossAppSerializationBinder : ISerializationBinder { public Type BindToType(string assemblyName, string typeName) { // 忽略原数据里的程序集名,用当前控制台应用的程序集类型 return Type.GetType($"{typeName}, {Assembly.GetExecutingAssembly().FullName}"); } public void BindToName(Type serializedType, out string assemblyName, out string typeName) { assemblyName = null; // 序列化时不输出程序集信息 typeName = serializedType.FullName; } }
如果你用的是System.Text.Json:
网站端(序列化时):
var jsonOptions = new JsonSerializerOptions { WriteIndented = true, TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => typeInfo.PolymorphismOptions = null } // 关闭多态类型信息写入 } }; string serializedData = JsonSerializer.Serialize(yourComunicadoInstance, jsonOptions);
控制台端(反序列化时):
var jsonOptions = new JsonSerializerOptions { TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => typeInfo.PolymorphismOptions = null } } }; var comunicado = JsonSerializer.Deserialize<Comunicado>(serializedData, jsonOptions);
三、检查属性定义的一致性
最后再确认一下两个应用里的PerfilDeAcesso[]属性定义完全一致:
- 两边都要有
virtual关键字(你代码里用了virtual,别一边有一边没有) - 不要有不一致的序列化特性(比如一边加了
[JsonIgnore],另一边没有) - 属性的getter/setter访问修饰符也要完全一样
比如两边的属性定义必须是:
public virtual PerfilDeAcesso[] PerfisDeAcesso { get; set; }
内容的提问来源于stack exchange,提问作者Cassio Henrique
相关产品推荐
相关产品推荐

