.NET 5 WPF中Newtonsoft.Json反序列化动态加载插件类型的问题
解决方案
你遇到的问题本质是Newtonsoft.Json默认的类型解析逻辑仅会查询编译期引用的程序集,不会主动扫描动态加载的插件程序集,通过自定义ISerializationBinder即可完美解决,无需额外编写复杂的解析逻辑。
实现步骤
1. 编写自定义序列化绑定器
自定义绑定器内部维护已加载的插件类型集合,供反序列化时匹配JSON中的$type字段:
public class PluginSerializationBinder : ISerializationBinder { // 存储所有已加载的插件类型,Key格式和JSON中$type的输出格式完全匹配 private readonly Dictionary<string, Type> _knownPluginTypes; public PluginSerializationBinder(IEnumerable<Type> loadedPluginTypes) { _knownPluginTypes = loadedPluginTypes.ToDictionary( type => $"{type.FullName},{type.Assembly.GetName().Name}", type => type ); } // 反序列化时触发:根据$type的字符串返回对应Type public Type BindToType(string assemblyName, string typeName) { string typeLookupKey = $"{typeName},{assemblyName}"; // 优先匹配插件类型,匹配失败走默认类型解析逻辑 if (_knownPluginTypes.TryGetValue(typeLookupKey, out var matchedType)) { return matchedType; } return Type.GetType(typeLookupKey); } // 序列化时触发:保持原有$type输出逻辑即可 public void BindToName(Type serializedType, out string assemblyName, out string typeName) { assemblyName = serializedType.Assembly.GetName().Name; typeName = serializedType.FullName; } }
2. 反序列化时注入绑定器
加载完所有插件后,把所有插件类型传入自定义绑定器,再配置到序列化设置中即可:
// 你的插件加载逻辑,建议把所有加载的插件类型统一维护到全局集合中 var pluginAssemblies = Assembly.LoadFile("plugin.dll"); var allLoadedPluginTypes = pluginAssemblies.GetTypes().Where(t => t.IsSubclassOf(typeof(BaseClass))).ToList(); // 配置序列化设置,注入自定义绑定器 var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, SerializationBinder = new PluginSerializationBinder(allLoadedPluginTypes) }; // 现在反序列化可以正常识别所有动态加载的插件类型 var readObject = JsonConvert.DeserializeObject<TypeOfMyModel>(content, settings);
运行时类型持久化说明
你通过Assembly.LoadFile加载的程序集,在当前应用域的整个生命周期内都会被识别,.NET 5+默认只有一个根应用域,只要你不主动卸载加载的程序集,这些类型在应用运行全程都可以正常使用,不需要额外处理。
注意:
TypeNameHandling.All存在反序列化注入安全风险,仅在你完全信任JSON文件来源的场景下使用。
内容的提问来源于stack exchange,提问作者Poc
相关产品推荐
相关产品推荐

