c# - 制作领域中立程序集的步骤是什么?

标签 c# .net appdomain

...这些步骤是否也可以应用于第 3 方程序集(可能已经是强名称的)?

我的问题的上下文应该不重要,但我还是要分享:我正在考虑制作一个记录器(或日志包装器),它始终知道要定位的“日志源”,而不管程序集是否使用它的是在一个应用程序域中,或者分布在多个应用程序域中。我认为实现这一目标的一种方法是拥有一个具有静态“LogSource”属性的域中立程序集。如果该静态属性设置在域中立程序集中,我认为所有应用程序域都会看到它。

最佳答案

程序集不会以任何特定方式标记为域中立的。您不必给它们一些特定的属性来使它们与域无关。 CLR 可以将任何程序集加载到共享域或触发程序集加载的域,具体取决于加载程序集的 CLR 实例的配置。

CLR 实例如何决定加载程序集由策略决定。有几种方法可以明确设置此策略:

作为域中立加载的程序集将加载到共享域中。应用程序域名在 CLRv4 中是“EE Shared Assembly Repository”。那不是真正的应用程序域,因为它没有数据也不能运行任何代码。加载到其中的程序集将在所有其他正在运行的应用程序域之间共享其代码。程序集中的字节代码只会被 JIT 编译一次。但是,程序集中的所有可变数据都将在运行域之间复制。 应用域之间不共享静态字段。每个应用域的静态字段将被复制,并且当引用相同的静态字段时,不同的应用域将在内存中的不同位置读取和写入。

另外:还有另一种静态字段 - RVA 静态,在当前进程中的所有应用程序域之间共享。在 C# 中无法声明这样的字段,但可以在 C++/CLI 中完成。

使用领域中立程序集需要权衡取舍。 对静态字段的访问速度较慢。由于它们仅进行一次 JIT,但可能会访问每个应用域静态字段的多个实例,因此对静态字段的任何访问都会通过额外的间接访问。当程序集直接加载到运行域中时,静态字段的地址可以直接嵌入到 JIT 代码中。但是,当编译到共享程序集中的代码试图访问静态字段时,它必须首先加载当前域的上下文,然后在其中找到该域的静态字段地址。

将程序集加载到共享域还是运行域的决定取决于您的用例,更具体地说,您将创建多少应用程序域以及您将加载到其中的核心类型。

  • 如果您加载运行基本相同代码的多个域,您会希望尽可能多地共享程序集,除非它会显着损害访问静态字段的性能。一个例子是一个应用程序为了隔离而决定在单独的应用程序域中运行它自己的部分代码。
  • 如果您使用不同的代码加载多个域,您最好只共享所有不同程序集可能常用的程序集。这些通常是 .NET Framework 自己的程序集和从 GAC 加载的所有程序集。 IIS 在运行 ASP.NET 应用程序时默认以这种方式工作。
  • 如果您只使用一个应用域,则不应共享任何内容。常规的 GUI 应用程序就是这样。

注意:mscorlib 始终加载到共享域中。

来源和进一步阅读:

关于c# - 制作领域中立程序集的步骤是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3058110/

相关文章:

.net - 由索引上的页锁引起的sql server compact死锁

c# - 事件未通过 AppDomain 触发

.net - 多个 .NET AppDomain 的代码示例

c# - 如何从另一个进程获取 .NET CLR 内存堆大小?

c# - WPF 功能区以编程方式折叠和展开

c# - 在 Windows 窗体中制作 WPF 渐变

.net - LINQ查询与SQL等效的性能

c# - 林克/C# : Selecting and summing items from the result of a group by?

.net - 在teamcity中构建nuget包

c# - 从另一个 WPF 应用程序加载 WPF 应用程序程序集,在同一 AppDomain 中获取错误 : Cannot create more than one System. Windows.Application 实例