在同一台机器上的 .NET 应用程序之间复制对象的最佳方法是什么?
What's the best way to copy objects between .NET applications on the same machine?
我在同一台计算机上有同一个 .NET (C#) 应用程序的两个实例 运行。我需要将一些相对复杂的对象从一个实例传递到另一个实例。执行此操作的最佳方法是什么。
作为背景,这些实例是我们的 Office 加载项,如果 Word 和 Excel 都是 运行,它们各自创建一个不同的加载项实例。无法让他们使用相同的实例。
这是一次性将数据从实例 A 传递到实例 B。我确实想到了一个命名管道,但我相信这将是一个皇家 PITA 来序列化和反序列化所有对象 - 它们很复杂.
第一步是确定您尝试共享的对象是否可以序列化。
最佳情况
如果它及其所有后代属性都是 POCO/Structs,那么这应该不是问题。首先引用 Newtonsoft.Json,然后使用下面的代码。
由于序列化器和反序列化器都将是 Newtonsoft.Json,我们可以使用类型名称处理并保留引用处理选项以允许序列化更复杂的类型。
var serializerSettings = new JsonSerializerSettings
{
{
Formatting = Formatting.Indented, // Can remove if you won't read output.
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple, // Don't force specific version of assembly.
ReferenceLoopHandling = ReferenceLoopHandling.Serialize, // Serialize reference loops, PreserveReferencesHandling will prevent infinite loop.
PreserveReferencesHandling = PreserveReferencesHandling.All, // Use $ref and $id for looped references.
TypeNameHandling = TypeNameHandling.All // Include type name of objects when serializing.
};
}
var json = JsonConvert.Serialize(obj, serializerSettings);
假设被序列化的类型及其所有 属性 后代具有无参数构造函数并且属性没有做任何奇怪的事情,这应该没有任何问题。
对此进行测试,如果有效,您可以删除 PreserveReferencesHandling、TypeNameHandling 和 ReferenceLoopHandling 选项;但是,如果对象具有引用循环或包含任何属性,其中引用 属性 包含继承类型的对象而不是属性定义类型的对象,则序列化可能会失败。
假设序列化成功,您可以使用您喜欢的 IPC 方法,只需传输 JSON 并在另一端反序列化。
对于内存映射文件,您可以使用本指南http://www.codingvision.net/tips-and-tricks/c-send-data-between-processes-w-memory-mapped-file
在该示例中,不使用 BinaryFormatter,而是使用 NewtonSoft.Json 的示例。
如果上述方法不起作用
其中一个属性或后代属性无法使用上述选项进行序列化。如果这是由于无参数构造函数造成的,那么您将需要创建自己的反序列化转换器。参见 https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm
如果后代 属性 类型之一由于其他原因无法序列化,您可能无法找到 "simple" 解决方案。
此时,您将必须为要发送的内容创建一个 DTO,并知道如何根据 DTO 中的数据在另一端构建您想要的内容。
通常这不是问题,除非属性被奇怪地使用(getter/setter 使用不安全代码,或有其他 "side effects")。我不熟悉 MS Office 库,但如果其中引用正在处理的文档的某些类型由于这个原因而无法序列化,我不会感到惊讶。
结论
您的问题表明您还没有尝试过序列化。你必须尝试,因为在你尝试失败之前,你不知道会遇到什么问题。
如果幸运的话,上面的 JSON 序列化代码就可以了。如果是这样,那么你的问题就解决了。使用命名管道或内存映射文件或其他任何东西,并将其加载到另一端。
如果它不能正常工作,无论如何都会很复杂。序列化是您唯一真正的选择,如果您引用的 MS Office 库类型执行一些奇怪的 native/unsafe 事情,则需要创建 DTO。
您当然可以自己编写不安全的代码并直接进行内存操作,而不是序列化……但这是非常不可取的,而且几乎肯定会失败。
我在同一台计算机上有同一个 .NET (C#) 应用程序的两个实例 运行。我需要将一些相对复杂的对象从一个实例传递到另一个实例。执行此操作的最佳方法是什么。
作为背景,这些实例是我们的 Office 加载项,如果 Word 和 Excel 都是 运行,它们各自创建一个不同的加载项实例。无法让他们使用相同的实例。
这是一次性将数据从实例 A 传递到实例 B。我确实想到了一个命名管道,但我相信这将是一个皇家 PITA 来序列化和反序列化所有对象 - 它们很复杂.
第一步是确定您尝试共享的对象是否可以序列化。
最佳情况
如果它及其所有后代属性都是 POCO/Structs,那么这应该不是问题。首先引用 Newtonsoft.Json,然后使用下面的代码。
由于序列化器和反序列化器都将是 Newtonsoft.Json,我们可以使用类型名称处理并保留引用处理选项以允许序列化更复杂的类型。
var serializerSettings = new JsonSerializerSettings
{
{
Formatting = Formatting.Indented, // Can remove if you won't read output.
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple, // Don't force specific version of assembly.
ReferenceLoopHandling = ReferenceLoopHandling.Serialize, // Serialize reference loops, PreserveReferencesHandling will prevent infinite loop.
PreserveReferencesHandling = PreserveReferencesHandling.All, // Use $ref and $id for looped references.
TypeNameHandling = TypeNameHandling.All // Include type name of objects when serializing.
};
}
var json = JsonConvert.Serialize(obj, serializerSettings);
假设被序列化的类型及其所有 属性 后代具有无参数构造函数并且属性没有做任何奇怪的事情,这应该没有任何问题。
对此进行测试,如果有效,您可以删除 PreserveReferencesHandling、TypeNameHandling 和 ReferenceLoopHandling 选项;但是,如果对象具有引用循环或包含任何属性,其中引用 属性 包含继承类型的对象而不是属性定义类型的对象,则序列化可能会失败。
假设序列化成功,您可以使用您喜欢的 IPC 方法,只需传输 JSON 并在另一端反序列化。
对于内存映射文件,您可以使用本指南http://www.codingvision.net/tips-and-tricks/c-send-data-between-processes-w-memory-mapped-file
在该示例中,不使用 BinaryFormatter,而是使用 NewtonSoft.Json 的示例。
如果上述方法不起作用
其中一个属性或后代属性无法使用上述选项进行序列化。如果这是由于无参数构造函数造成的,那么您将需要创建自己的反序列化转换器。参见 https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm
如果后代 属性 类型之一由于其他原因无法序列化,您可能无法找到 "simple" 解决方案。
此时,您将必须为要发送的内容创建一个 DTO,并知道如何根据 DTO 中的数据在另一端构建您想要的内容。
通常这不是问题,除非属性被奇怪地使用(getter/setter 使用不安全代码,或有其他 "side effects")。我不熟悉 MS Office 库,但如果其中引用正在处理的文档的某些类型由于这个原因而无法序列化,我不会感到惊讶。
结论
您的问题表明您还没有尝试过序列化。你必须尝试,因为在你尝试失败之前,你不知道会遇到什么问题。
如果幸运的话,上面的 JSON 序列化代码就可以了。如果是这样,那么你的问题就解决了。使用命名管道或内存映射文件或其他任何东西,并将其加载到另一端。
如果它不能正常工作,无论如何都会很复杂。序列化是您唯一真正的选择,如果您引用的 MS Office 库类型执行一些奇怪的 native/unsafe 事情,则需要创建 DTO。
您当然可以自己编写不安全的代码并直接进行内存操作,而不是序列化……但这是非常不可取的,而且几乎肯定会失败。