跨 AppDomain 的自定义序列化

Posted

技术标签:

【中文标题】跨 AppDomain 的自定义序列化【英文标题】:Custom serialization across AppDomain 【发布时间】:2015-02-09 17:02:11 【问题描述】:

短版:我正在尝试自定义跨 AppDomain 边界的序列化,特别是为了处理 AppDomain 的每一侧都有稍微不同的类版本的情况。我该怎么做?

长版:我们使用 AppDomains 来管理较大应用程序下的不同子模块。我们希望独立部署这些子模块,因此使用 AppDomains。我们在主应用程序和子模块之间有一个共享的contracts dll,不同版本的contracts dll 最终会出现在各种子模块中,因为每个子模块的更新频率都低于主应用程序。结果,有时会在contracts dll中添加一个新字段或新类型,并在主应用程序中使用,但子模块不知道如何序列化它。

我想我可以通过自定义序列化过程来解决这个问题,特别是 SerializationBinder.BindToType。但是要做到这一点,我需要告诉 AppDomain 的每一端都使用这个序列化绑定器。我该怎么做呢?我在网上看到的所有示例都有对 Serialize() 和 Deserialize() 的显式调用。我初始化 AppDomain 的代码是:

var appDomainSetup = new AppDomainSetup

    ApplicationBase = config.BasePath,
    ShadowCopyFiles = "true",
    ConfigurationFile = File.Exists(configPath) ? configPath : null,
;

AppDomain.CreateDomain("myappdomain", null, appDomainSetup);

感谢您对此的帮助。

【问题讨论】:

【参考方案1】:

有一个框架可以完全满足您的需求。它在基类库中,名为MAF (Managed AddIn Framework),您可以通过引用System.AddIn.dll来使用它。

MAF 包含三个概念:

    管道 发现 激活

您可以通过创建多个接口并在它们之间实现适配器来定义 AddIn 管道。这是一个乏味的过程,但它使您能够对接口进行 AddIn 端和主机端版本控制。您可以在新主机中使用旧插件,也可以在旧版本主机中使用新插件,前提是您部署了适当的适配器。整个过程描述over here。

发现使您的主机应用程序能够枚举它在您配置的位置找到的所有插件,包括元数据。

激活然后使用在发现阶段找到的任何AddInToken 来激活插件。您可以在多种隔离模型之间进行选择,包括 AppDomains,它们应该非常适合您的用例。

我曾多次在不同的项目中使用过该框架。如果您习惯了有些复杂的管道开发过程并遇到了几个陷阱(始终将“复制本地”设置为 false,以便在您的 AddIn 中引用 AddInViews),这是值得的。

有关创建示例应用程序的详尽教程,look here。

【讨论】:

谢谢弗兰克。这很有可能成为我们的长期答案,我认为我可以解决我们当前的问题,因为此时我们只有 1 个子模块。

以上是关于跨 AppDomain 的自定义序列化的主要内容,如果未能解决你的问题,请参考以下文章

跨 AppDomain 传递自定义对象

程序集无法加载到受限的 AppDomain

在 C# 中的自定义 appdomain 中加载 dll

AppDomains之间如何最好地进行通信?

如何跨 AppDomain 将引用作为方法参数传递?

跨 AppDomain 边界的垃圾收集对象