从字节数组加载Assembly时AppDomain程序集未找到问题求助
解决AppDomain加载字节数组后找不到程序集的问题
我太懂你花30多小时卡在这里的崩溃感了——这个问题其实是AppDomain.Load(byte[])的一个极易踩中的陷阱,咱们一步步把它捋清楚解决掉。
问题根源
你用domain.Load(_myBytes)的时候,这个方法根本不是在你创建的目标AppDomain里加载程序集!它是在调用这个方法的当前AppDomain中加载的,目标AppDomain完全没拿到这个程序集,后续枚举自然会报「AppDomain Assembly not found」。这是官方文档里藏得比较深的细节,很多人第一次用都会踩坑。
解决方案:用目标AppDomain内的代理对象加载
要让程序集真正加载到目标AppDomain里,你需要借助MarshalByRefObject创建一个跨AppDomain的代理类,让加载操作在目标AppDomain内部执行。
步骤1:创建跨AppDomain的加载器类
这个类会在目标AppDomain中实例化,所有加载和枚举操作都由它在目标域内完成:
public class AssemblyLoader : MarshalByRefObject { private Assembly _loadedAssembly; // 在目标AppDomain内部加载字节数组形式的程序集 public void LoadAssembly(byte[] assemblyBytes) { _loadedAssembly = Assembly.Load(assemblyBytes); } // 从目标AppDomain中获取所有类型的名称 public List<string> GetAllTypeNames() { if (_loadedAssembly == null) throw new InvalidOperationException("请先加载程序集"); return _loadedAssembly.GetTypes() .Select(type => type.FullName) .ToList(); } }
步骤2:修改主程序逻辑
现在调整你的代码,让目标AppDomain自己去加载程序集:
// 读取dll字节数组并删除原文件 byte[] _myBytes = File.ReadAllBytes(@"D:\Projects\AppDomainTest\plugin.dll"); File.Delete(@"D:\Projects\AppDomainTest\plugin.dll"); // 创建目标AppDomain var domain = AppDomain.CreateDomain("plugintest", null, null, null, false); try { // 在目标AppDomain中创建AssemblyLoader的实例(通过透明代理) var loader = (AssemblyLoader)domain.CreateInstanceAndUnwrap( typeof(AssemblyLoader).Assembly.FullName, typeof(AssemblyLoader).FullName ); // 让目标AppDomain自己加载字节数组 loader.LoadAssembly(_myBytes); // 从目标AppDomain获取所有类型 var typeNames = loader.GetAllTypeNames(); foreach (var typeName in typeNames) { Console.WriteLine(typeName); } } finally { // 用完记得卸载AppDomain(如果不需要保留的话) AppDomain.Unload(domain); }
额外说明
- 为什么必须用代理?因为AppDomain是隔离的,你不能直接在当前域操作另一个域的对象。
MarshalByRefObject会让.NET为你创建一个透明代理,你在当前域调用代理方法时,实际执行逻辑会跑到目标AppDomain里。 - 如果你需要更多操作(比如创建类型实例),都可以在
AssemblyLoader里添加对应的方法,确保所有操作都在目标域内完成。
内容的提问来源于stack exchange,提问作者Jenny
相关产品推荐
相关产品推荐

