gpt4 book ai didi

c# - Mef:尝试从另一个应用程序域加载ApiController时,“无法序列化”

转载 作者:行者123 更新时间:2023-11-30 16:40:57 27 4
gpt4 key购买 nike

我正在尝试找到一种通过添加新的ApiController(由另一服务下载)在运行时更新Asp.net Web API(.Net Framework 4.5)的方法(而不回收主appdomain)。

我尝试使用Mef并能够在当前appdomain中加载新的ApiController,但是在尝试更新现有插件时我卡住了(程序集已添加到appdomain中,所以我无法添加新的)。
因此,我决定在一个单独的appdomain中加载包含ApiController的插件,并使用MarshalByRefObject从主appdomain中加载它,但事实证明ApiConroller无法序列化。

你知道我该如何序列化吗?
你知道替代品吗?

编辑:

如果对程序集进行了签名,我设法加载了不同版本的程序集(在同一appdomain中),但是它不符合我的要求。

最佳答案

我没有使用MEF(因为与MAF矛盾,因为从头开始实现它的功能同样容易),但是这样,我对裸露的AppDomains有一定的经验。

不看代码很难说很多,但是从您写的内容来看,在我看来您正在混淆某些事情。

正如您可能已经知道并且已经指出的那样,您实际上无法更新已经加载的程序集。加载它的另一个版本(具有不同的签名)意味着您已加载了两个不同的程序集。其中的类型将具有不同的强名称。如果需要,您实际上可以处理。卸载程序集的唯一方法是卸载包含该程序集的appdomain。

我的问题是这句话:


  ...在单独的appdomain中加载包含ApiController的插件
  并使用MarshalByRefObject从主appdomain加载它


类型(类)定义+代码和实例数据是两件事。将程序集加载到appdomain中意味着您正在加载类型定义和代码。当您想跨应用程序域边界传输实例数据时,就会看到序列化。您无法在编写时从其他应用程序域中加载类型定义和代码(实际上可以,但是我怀疑您需要这样做)。为了能够传输实例数据,双方都需要了解要传输的实例的类型定义。在这种情况下,序列化和传输由.net远程运行时管理。
您有两种选择:要么移动所有实例数据并一直对其进行序列化,要么按照您说的那样选择MarshalByObjRef方式。让我们继续。为了能够使用另一个应用程序域中的实例,您将需要使用激活器在另一个应用程序域中实例化类型(在这种情况下,您不能使用new运算符),并获得对其的引用。将基于您知道的类型(也可以是接口或基类,不仅是确切的类型)作为代理。在这种情况下,反射受到某种程度的限制,asp.net为弄清远程对象的方法所准备的东西更少了,但是您可以通过适当的接口来帮助它。

因此,假设您在另一个appdomain中创建了控制器的一个实例,并且在其上有一个远程引用,该引用可分配给定义您需要公开给asp.net的所有方法的接口类型。现在,当尝试访问控制器类的成员时,就会看到序列化。每个方法参数和方法返回类型都需要可序列化。但是类本身不是,因为它是一个MashalByObjRef后代,并且不会被混搭为一个实例。 MashalByObjRef与将程序集加载到appdomain中的方式无关。

可是等等! MarshalByObjRefApiController都是抽象类。您想如何从这两者派生实际的控制器类?你不能因此,我认为您不能直接使用其他应用程序域中的apicontrollers。

我可以想象两件事:

1)继续将新签名版本加载到同一程序集中,并自定义路由机制以将请求定向到最新版本(可能仍然无效,但可能仍是一个很好的起点:https://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/)。
当然,在重新启动时,如果不需要并行具有多个版本,则应仅加载最新版本。

2)建立一个稍微复杂的基础架构:


定义控制器逻辑的接口
创建无版本且无逻辑的apicontroller,但能够创建和卸载应用程序域,将程序集加载到其中,保留对从上面在其中创建接口的实例的引用,并将请求定向到这些实例
请注意,您将无法将某些内容(例如控制器上下文)传递给另一个应用程序域中的逻辑,您将必须提取需要的内容或在另一端重新创建
这样,您可以在“远程”应用程序域中具有逻辑MarshalByObjRef子代,而在主应用程序域中具有控制器ApiController子代。
我将创建一个扩展ApiController的临时抽象类,该类可以自行处理上述分隔。应用程序的其余部分不会意识到这一点。
请注意远程处理中涉及的终生服务,您可以通过使用赞助者或覆盖MarshalByObjRef的某些方法来处理。


都不是简单的方法,您将面临进一步的挑战...

关于c# - Mef:尝试从另一个应用程序域加载ApiController时,“无法序列化”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50081508/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com