






















《CLR Via C#》第22章聚焦CLR寄宿和AppDomain,这是.NET框架中管理托管代码执行与隔离的核心机制
CLR寄宿是指将.NET运行时(CLR)嵌入到宿主进程(如ASP.NET、SQL Server或自定义应用)中运行。宿主控制CLR的加载、初始化和行为,提供托管代码的执行环境。
CorBindToRuntimeEx等API)。AppDomain是CLR中的轻量级隔离单元,运行在同一进程内,提供代码隔离、动态加载和卸载功能。相比进程,AppDomain开销更低,适合需要隔离但共享进程资源的场景。
以下图表展示了宿主进程、CLR和AppDomain的层次结构:
graph TD A[宿主进程] -->|加载| B[CLR] B -->|创建| C[默认AppDomain] B -->|创建| D[自定义AppDomain 1] B -->|创建| E[自定义AppDomain 2] C -->|运行| F[程序集A] D -->|运行| G[程序集B] E -->|运行| H[程序集C] D -->|跨域通信| E
宿主通过ICorRuntimeHost或ICLRRuntimeHost接口加载CLR,并可配置运行时参数。以下是一个简化的自定义宿主示例:
using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("mscoree.dll", CharSet = CharSet.Unicode)]
static extern int CorBindToRuntimeEx(
string pwszVersion, string pwszBuildFlavor,
uint startupFlags, ref Guid rclsid, ref Guid riid,
out IntPtr ppv);
static void Main()
{
Guid clsid = new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E"); // CLSID_CorRuntimeHost
Guid riid = new Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E"); // IID_ICorRuntimeHost
IntPtr ppv;
int hr = CorBindToRuntimeEx("v4.0.30319", "wks", 0, ref clsid, ref riid, out ppv);
if (hr >= 0)
{
Console.WriteLine("CLR loaded successfully!");
// 进一步初始化和运行代码
}
}
}
v4.0.30319)和工作站模式(wks)。AppDomain的创建和使用是本章的重点。以下是一个完整的示例,展示如何创建AppDomain、加载程序集并实现跨域通信:
using System;
using System.Reflection;
public class Plugin : MarshalByRefObject
{
public void Execute()
{
Console.WriteLine($"Running in AppDomain: {AppDomain.CurrentDomain.FriendlyName}");
}
}
class Program
{
static void Main()
{
// 创建新AppDomain
AppDomainSetup setup = new AppDomainSetup
{
ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
};
AppDomain pluginDomain = AppDomain.CreateDomain("PluginDomain", null, setup);
// 加载插件并执行
try
{
Plugin plugin = (Plugin)pluginDomain.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName, "Plugin");
plugin.Execute();
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
// 卸载AppDomain
AppDomain.Unload(pluginDomain);
}
}
}
MarshalByRefObject实现代理通信。MarshalByRefObject或实现序列化。跨AppDomain通信是实际应用的难点。以下是两种方式的对比:
| 方式 | 描述 | 适用场景 |
|---|---|---|
示例(Marshal-by-Value):
[Serializable]
public class Data
{
public string Message { get; set; }
}
public class Worker : MarshalByRefObject
{
public Data GetData()
{
return new Data { Message = "Hello from AppDomain!" };
}
}
[Serializable]标记可序列化类型。MarshalByRefObject中传递复杂状态,优先使用简单数据。sequenceDiagram participant A as AppDomain A participant B as AppDomain B participant P as Proxy A->>B: CreateInstanceAndUnwrap B-->>P: Return Proxy A->>P: Call Method P->>B: Forward Call B-->>P: Return Result P-->>A: Return Result
AppDomain是实现插件架构的理想选择。核心步骤:
Assembly.LoadFrom动态加载程序集。MarshalByRefObject与插件交互。AppDomain.Unload卸载插件。通过PermissionSet限制AppDomain权限:
PermissionSet perms = new PermissionSet(PermissionState.None);
perms.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, @"C:\data"));
AppDomainSetup setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory };
AppDomain secureDomain = AppDomain.CreateDomain("SecureDomain", null, setup, perms);
第22章深入揭示了CLR寄宿和AppDomain的强大功能,为开发者提供了在托管环境中实现隔离、动态性和安全性的工具。核心要点包括:
注意事项:
通过掌握本章内容,开发者可以构建更灵活、可扩展和安全的.NET应用程序,尤其在动态加载和隔离需求高的场景中。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。