Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关于如何使用插件式体系结构实现c#主机应用程序的问题_C#_.net_Multithreading_Plugins_Appdomain - Fatal编程技术网

关于如何使用插件式体系结构实现c#主机应用程序的问题

关于如何使用插件式体系结构实现c#主机应用程序的问题,c#,.net,multithreading,plugins,appdomain,C#,.net,Multithreading,Plugins,Appdomain,我希望有一个应用程序可以作为许多其他小型应用程序的主机。这些应用程序中的每一个都应该作为这个主应用程序的插件。我称它们为插件并不是因为它们向主应用程序添加了一些东西,而是因为它们只能与这个主机应用程序一起工作,因为它们依赖于它的一些服务 我的想法是让这些插件在不同的应用程序域中运行。问题似乎是,我的主机应用程序应该有一组我的插件想要使用的服务,根据我的理解,让数据从不同的应用程序域流入流出并不是一件好事 一方面,我希望它们像独立的应用程序一样运行(尽管,正如我所说,它们需要使用主机应用程序服务很

我希望有一个应用程序可以作为许多其他小型应用程序的主机。这些应用程序中的每一个都应该作为这个主应用程序的插件。我称它们为插件并不是因为它们向主应用程序添加了一些东西,而是因为它们只能与这个主机应用程序一起工作,因为它们依赖于它的一些服务

我的想法是让这些插件在不同的应用程序域中运行。问题似乎是,我的主机应用程序应该有一组我的插件想要使用的服务,根据我的理解,让数据从不同的应用程序域流入流出并不是一件好事

一方面,我希望它们像独立的应用程序一样运行(尽管,正如我所说,它们需要使用主机应用程序服务很多次),但另一方面,我希望如果它们中的任何一个崩溃,我的主应用程序都不会受到影响

对于这种情况,最好的(.NET)方法是什么?让它们都在相同的AppDomain上运行,但每个都在不同的线程中?使用不同的应用程序域?每个“插件”一个?如何使它们与主机应用程序通信?还有别的办法吗

虽然速度在这里不是一个问题,但我不希望函数调用比使用普通的.NET应用程序时慢那么多

谢谢


编辑:也许我真的需要使用不同的AppDomain。从我所阅读的内容来看,在不同的AppDomain中加载程序集是以后能够从进程中卸载程序集的唯一方法。

这是一个有趣的问题

我的第一个想法是在插件应用程序中实现主机应用程序的接口,以允许它们通过反射进行通信,但这只允许通信,不会带来真正的“沙盒式”体系结构

我的第二个想法是设计一个面向服务的平台。主机应用程序将是一种“插件广播器”,它将在不同的线程上发布ServiceHost中的插件。由于这需要具有真正的响应性和“无脑配置”,主机应用程序可以通过命名管道通道(NetNamedPipesBinding for WCF)与插件通信,这意味着它只与本地主机管道通信,根本不需要任何网络配置或知识。我认为这可能是解决你问题的好办法


问候。

这取决于您希望允许扩展的信任度。我正在开发一个类似的应用程序,我选择主要信任扩展代码,因为这大大简化了事情。我从一个公共线程调用代码(在我的例子中,扩展并不真正在任何连续循环中“运行”,而是执行主应用程序想要执行的某些任务),并捕获该线程中的异常,以便提供有用的警告,指出加载的扩展行为不正常

目前,没有任何东西可以阻止这些扩展启动它们自己的线程,这些线程可能会导致整个应用程序崩溃,但我不得不在安全性和复杂性之间做出权衡。我的应用程序不是关键任务(不像Web服务器或数据库服务器),所以我认为一个安全的扩展可以降低我的应用程序是一个可以接受的风险。我提供了保护措施,以更礼貌地涵盖最常见的故障案例,并将其留给插件开发人员(目前他们主要是内部人员)来清理他们的bug


关于卸载,是的,如果将程序集放置在AppDomain中,则只能卸载程序集的代码和元数据。也就是说,除非您希望在程序的整个生命周期中频繁地加载和卸载代码,否则将代码保存在内存中的开销不一定是问题。当您停止“使用”它时,使用程序集中类型的任何实际实例或资源仍将由GC清理,因此它仍在内存中这一事实并不意味着内存泄漏

如果您的主要用例是一系列插件,您可以在启动时找到这些插件,然后在应用程序运行时提供一个实例化选项,那么我建议您调查与启动时加载所有插件并保持加载相关的实际内存占用情况。如果使用AppDomains,也会有额外的开销(例如,代理对象的内存和支持AppDomain封送的加载/JIT代码)。还有和封送和助理序列化相关的CPU开销

简言之,我只会在以下情况之一为真时使用AppDomains:

  • 为了代码安全,我希望获得真正的隔离(即,我需要以隔离的方式运行不受信任的代码)

  • 我的应用程序是任务关键型的,我绝对需要确保,如果插件失败,它不能关闭我的核心应用程序

  • 我需要反复加载和卸载同一个插件,以支持动态更改DLL。这主要是如果我的应用程序无法停止运行,但我想在它仍在运行时热补丁插件


我不希望AppDomains仅仅是为了通过允许卸载来减少可能的内存占用。

我已经在System.Addin命名空间中使用托管加载项框架(MAF)实现了一些类似的功能。使用MAF,您可以将外接程序打包为单独的DLL,主机应用程序可以在其应用程序域、所有外接程序的单独域或其自己域中的每个外接程序中发现并启动这些DLL。使用卷影复制和独立域,您甚至可以在不关闭hostapp的情况下更新加载项

您的主机应用程序和加载项通过您从MAF接口派生的契约进行通信。您可以在主机和加载项之间来回发送对象。COTNR法案提供了一个黑色的-