You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core WPF运行时跨AppDomain注入类型及动态替换可行吗?

.NET Core WPF中跨隔离上下文加载同名类型并动态替换的实现

问题描述

能否在.NET Core WPF应用运行的任意阶段,将包含MyType类型的程序集加载到独立的隔离上下文(原AppDomain替代方案)并在主上下文使用?之后能否销毁该隔离上下文,加载另一个同样包含MyType类型的程序集并在主域中使用?

目标是无需重启应用、不使用dynamic对象以避免装箱/拆箱,实现Value的多种类型适配。

示例代码结构:

// 主上下文代码
var list = new List<IMyType>(); // 使用共享接口统一处理

// 第一个隔离上下文加载的程序集中的类型
public class MyType : IMyType
{
    public string Value { get; set; }
    object IMyType.Value => Value;
}

// 第二个隔离上下文加载的程序集中的类型
public class MyType : IMyType
{
    public int Value { get; set; }
    object IMyType.Value => Value;
}

核心结论与实现方案

1. .NET Core中AppDomain的现状

.NET Core及后续版本(.NET 5+)已彻底移除AppDomain的隔离与卸载能力,官方推荐使用AssemblyLoadContext(简称ALC)作为程序集隔离加载、卸载的替代方案,因此无法通过传统AppDomain方式实现需求,必须切换到ALC方案。

2. 具体实现步骤

(1)定义共享接口

在主应用和所有待加载的程序集之间共享一个统一接口,让主上下文能通过接口访问不同版本MyType的Value成员,完全避免dynamic:

// 放在主应用、所有插件程序集都能引用的独立类库中
public interface IMyType
{
    object Value { get; }
    // 也可按需添加强类型方法,比如:
    // T GetValue<T>();
}

(2)用AssemblyLoadContext加载程序集

创建可回收的ALC实例加载目标程序集,通过反射创建MyType实例并转换为IMyType接口:

// 加载第一个程序集
var alc1 = new AssemblyLoadContext("MyTypeAssembly1", isCollectible: true);
var assembly1 = alc1.LoadFromAssemblyPath(@"path\to\first\MyTypeAssembly.dll");
var myType1 = (IMyType)Activator.CreateInstance(assembly1.GetType("MyType"));
list.Add(myType1);

// 访问Value
string stringValue = (string)myType1.Value;

(3)卸载隔离上下文并加载新程序集

切换程序集前,必须释放所有对当前ALC中对象的引用,再调用Unload()卸载ALC,最后创建新ALC加载第二个程序集:

// 释放对第一个ALC中对象的所有引用
list.Remove(myType1);
myType1 = null;

// 卸载第一个ALC
alc1.Unload();

// 加载第二个程序集
var alc2 = new AssemblyLoadContext("MyTypeAssembly2", isCollectible: true);
var assembly2 = alc2.LoadFromAssemblyPath(@"path\to\second\MyTypeAssembly.dll");
var myType2 = (IMyType)Activator.CreateInstance(assembly2.GetType("MyType"));
list.Add(myType2);

// 访问Value
int intValue = (int)myType2.Value;

3. 关键注意事项

  • 必须创建可回收ALC:初始化时需设置isCollectible: true,否则该ALC无法被卸载。
  • 彻底释放引用:卸载ALC前,主上下文不能保留任何来自该ALC的对象引用,否则GC无法回收资源,ALC也无法真正卸载。
  • 接口版本一致性:所有加载的程序集必须引用同一个接口类库,确保主上下文与隔离上下文的IMyType是同一类型,否则类型转换会失败。
  • 避免直接引用MyType:主上下文不能直接引用MyType类型,只能通过IMyType接口交互,否则目标程序集会被加载到主ALC中,无法卸载。

内容的提问来源于stack exchange,提问作者Boppity Bop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 17:17:24