在同一台机器上的 .NET 应用程序之间复制对象的最佳方式是啥? [关闭]
Posted
技术标签:
【中文标题】在同一台机器上的 .NET 应用程序之间复制对象的最佳方式是啥? [关闭]【英文标题】:What's the best way to copy objects between .NET applications on the same machine? [closed]在同一台机器上的 .NET 应用程序之间复制对象的最佳方式是什么? [关闭] 【发布时间】:2018-04-20 16:30:45 【问题描述】:我在同一台计算机上运行相同的 .NET (C#) 应用程序的两个实例。我需要将一些相对复杂的对象从一个实例传递到另一个实例。最好的方法是什么。
作为背景,这些实例是我们的 Office 插件,如果 Word 和 Excel 都在运行,它们会各自创建一个不同的插件实例。没有办法让他们使用同一个实例。
这是一次性将数据从实例 A 传递到实例 B。我确实想到了一个命名管道,但我相信这将是一个用于序列化和反序列化所有对象的皇家 PITA - 它们很复杂。
【问题讨论】:
澄清一下,您是在询问一次性按值副本(即序列化+反序列化)吗?您对引用传递、DCOM、.NET Remoting 等不感兴趣? 最简单的可能是创建一个系统范围的共享命名管道,然后从JsonConvert
提供它。
@Dai - 我更新了我的问题来回答你的 cmets。谢谢
有几种 .NET 进程互操作机制。这完全取决于序列化对象的难易程度,但程序员倾向于将 WCF 用于“复杂对象”。
@HansPassant 我强烈反对 WCF,尤其是因为它实际上是 EOL 的。 WCF 是一个构建在不同 IPC 方法(net.tcp
、HTTP 等)之上的重型框架,它不能解决序列化问题,因为您需要定义新的 [DataContract]
DTO 类或使用 [DataMember]
注释所有内容或ISerializable
.
【参考方案1】:
第一步是确定您尝试共享的对象是否可以序列化。
最佳案例场景
如果它和它的所有后代属性都是 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
如果其中一种后代属性类型由于某些其他原因而无法序列化,那么您可能无法获得“简单”的解决方案。
此时,您将不得不为您尝试发送的内容创建一个 DTO,并且知道如何从 DTO 中的数据构建您想要的另一端。
通常这不是问题,除非属性被奇怪地使用(getter/setter 使用不安全的代码,或有其他“副作用”)。我不熟悉 MS Office 库,但如果其中一些引用正在处理的文档的类型由于这个原因而不能序列化,我不会感到惊讶。
结论
您的问题表明您尚未尝试序列化。你必须尝试,因为你不知道你会遇到什么问题,直到你尝试并且失败了。
如果幸运的话,上面的 JSON 序列化代码就可以正常工作。如果是这样,那么你的问题就解决了。使用命名管道或内存映射文件或其他任何东西,然后在另一端加载它。
如果它不能正常工作,那么无论如何它都会变得复杂。序列化是您唯一真正的选择,如果您引用的 MS Office 库类型执行一些时髦的本机/不安全操作,则需要创建 DTO。
您当然可以自己处理不安全的代码并直接操作内存而不是序列化...但这是非常不可取的,而且几乎肯定会失败。
【讨论】:
谢谢。这是我所有的代码,所以我可以在类中添加任何需要的东西。谢谢 你对 IPC(总是同一台机器)-命名管道有什么建议?以上是关于在同一台机器上的 .NET 应用程序之间复制对象的最佳方式是啥? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
在 .NET 中,同一台机器上的两个进程进行通信的最佳方式是啥?
如何在opensuse中的同一台机器上的VM和docker之间共享目录?
用于 Windows 和 Linux 的同一台机器上的套接字
同一台机器上的 SQL Server Express,还是外部共享的 SQL Server Standard? (对于 ASP.NET 站点)