c# - 动态装配解析/管理

标签 c# wcf automation datacontractserializer

短版

我有一个使用插件基础结构的应用程序。插件具有可配置的属性,可帮助它们了解如何完成工作。插件按配置文件分组以定义如何完成任务,配置文件存储在由 DataContractSerializer 序列化的 XML 文件中。问题是在读取配置文件时,应用程序反序列化必须了解配置文件中定义的所有插件。我正在寻找一种方法来处理未知插件的解析。请参阅下面提议的解决方案部分,了解我已经考虑实现的一些想法,但我对任何事情都持开放态度(尽管我不想重新发明应用程序)。

详情

背景

我开发了一种业务流程自动化系统,供我目前在 C# 4 中工作的公司内部使用。它详尽地使用了“插件”来定义一切(从要执行的任务到工作单元的定义)并严重依赖动态配置模型,而动态配置模型又依赖 C# 4/DLR 动态对象来完成作业。由于其动态特性,它在执行时有点重,但它始终如一地工作并且性能足以满足我们的需求。

它包括一个 WinForms 配置 UI,该 UI 广泛使用反射来确定插件的可配置属性/字段,以及定义要处理的每个工作单元的属性/字段。 UI 也建立在 BPA 引擎之上,因此它对允许引擎完成其工作的(松散)对象模型有透彻的了解,巧合的是,这导致了一些用户体验的改进,例如,即席作业执行和用户输入的配置时验证。再次有改进的余地,但是,它似乎完成了它的工作。

配置 UI 使用 DataContractSerializer 来序列化/反序列化指定的设置,因此必须在配置加载之前(或在加载时)加载配置引用的任何插件。

结构

BPA 引擎被实现为一个共享程序集 (DLL),它被 BPA 服务(Windows 服务)、配置 UI(WinForms 应用程序)和插件测试器(Windows 服务的控制台应用程序版本)引用。引用共享程序集的三个应用程序中的每一个都只包含执行其特定目的所需的最少量代码。此外,所有插件都必须引用一个非常薄的程序集,该程序集基本上只定义了插件必须实现的接口(interface)。

问题

由于应用程序中使用了可扩展性模型,因此一直要求配置 UI 与服务应用程序从同一目录(在同一台 PC 上)运行。这样 UI 总是知道服务知道的所有程序集,因此它们可以被反序列化而不会遇到丢失的程序集。现在我们即将推出该系统,出于安全目的,我们的网络管理员要求允许在我们网络中的任何 PC 上远程配置 UI。通常,如果总是有一组已知的程序集要部署,则这不会成为问题,但是,由于能够使用用户构建的程序集扩展应用程序,因此必须有一种方法来解析插件所在的程序集可以实例化/使用。

提议的(可能很明显)解决方案

将 WCF 服务添加到服务应用程序,以允许对该服务实例了解的配置进行典型的 CRUD 操作,并重新设计配置 UI,使其更像具有连接/断开连接模型的 SSMS。这并没有真正解决问题,因此我们还需要从 Service 应用程序公开某种 ServiceContract 以允许查询它知道/有权访问的程序集。这很好而且相当直接,但是问题出现了,“UI 应该什么时候发现服务知道的程序集?”在连接时,我们可以将所有程序集从服务发送到 UI,以确保它始终知道服务执行的所有程序集,但这会因 AppDomain 管理(可能是不必要的)和程序集版本冲突而变得困惑。所以我建议挂入 AppDomain.AssemblyResolve/AppDomain.TypeResolve 事件,只下载客户端还不知道的程序集,并且只在需要时下载。这不一定清除 AppDomain 管理问题,但它肯定有助于解决版本冲突和相关问题。

问题

如果你一直坚持我这么久,我为你鼓掌并感谢你,但现在我终于要解决这里的实际问题了。经过几个月的研究并最终得出结论,我想知道这里是否有人不得不处理类似的问题,以及您如何处理陷阱和缺点?是否有我完全错过的标准方法来处理这个问题,或者您是否有任何基于您过去如何成功处理这个问题的建议?您是否发现所提议的方法有任何问题,或者您能否提供替代方案?

我知道并不是每个人都生活在我的脑海中,所以如果您需要进一步的澄清/解释,请告诉我。谢谢!

更新

我给了 MEF 一个公平的震动,觉得它对我的目的来说太简单了。并不是不能一心一意地处理我的应用程序的插件需求,问题是这样做太麻烦和肮脏而无法实现。这是一个很好的建议,它有很大的潜力,但在目前的状态下,它还没有。

关于我提出的解决方案的任何其他想法或反馈?

更新

我不知道我遇到的问题是否过于局部化,是否我未能正确描述我想要实现的目标,或者这个问题是否太长而无法完整阅读;但是我收到的少数答案非常有用,足以帮助我以不同的方式思考问题并找出我所追求的一些缺点。

简而言之,我试图做的是采用三个应用程序,它们在当前状态下使用公共(public)目录结构共享信息(配置/程序集),并尝试使这些应用程序在对可用性和体系结构影响最小的情况下跨网络工作。

文件共享似乎是这个问题的明显答案(正如@SimonMourier 在评论中提出的那样),但使用它们会导致缺乏控制和可调试性 出了点问题。我可以将它们视为可行的短期解决方案,但从长远来看,它们似乎并不可行。

最佳答案

tl;dr,但我 90% 确定您应该查看 MEF .
当我第一次看到它时,我就像“啊,另一个首字母缩略词”,但你会发现它非常简单,并且它内置于 .NET 4 中。最重要的是,它甚至可以在单声道上无缝运行,而且比在听到它和编译 hello worlds 以使用这些功能之间的一个小时(包括咖啡休息时间)。真的就是这么简单。

基本上,您“导出”程序集中的某些内容并将其“导入”到另一个程序集中(全部通过简单的属性修饰),然后您选择搜索它的位置(例如,在应用程序目录、插件文件夹等中)。

编辑:如果您尝试在配置加载时即时下载和加载(并可能缓存)插件怎么办?

关于c# - 动态装配解析/管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8641799/

相关文章:

c# - 如何将数据从datatable更新到sql表?

c# - Autofac 的 None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder'

c# - 在局域网中搜索WCF服务?

forms - 从PDF创建可填充的PDF

c# - LINQ 查询问题,序列不包含任何元素

c# - 全局异常处理 Web Api 2

c# - DynamicObject 对于空值的行为不同

c# - 未找到 WCF 端点

c# - 如何使用 C# 在 excel 中突出显示数据范围?

macos - 苹果操作系统 X : interacting with an application programmatically