我想加载到AppDomain具有复杂引用树的新程序集(MyDll.dll-> Microsoft.Office.Interop.Excel.dll-> Microsoft.Vbe.Interop.dll-> Office.dll-> stdole.dll)
AppDomain
据我了解,将程序集加载到时AppDomain,其引用不会自动加载,而我必须手动加载它们。因此,当我这样做时:
string dir = @"SomePath"; // different from AppDomain.CurrentDomain.BaseDirectory string path = System.IO.Path.Combine(dir, "MyDll.dll"); AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation; setup.ApplicationBase = dir; AppDomain domain = AppDomain.CreateDomain("SomeAppDomain", null, setup); domain.Load(AssemblyName.GetAssemblyName(path));
并得到FileNotFoundException:
FileNotFoundException
无法加载文件或程序集’MyDll,版本= 1.0.0.0,文化=中性,PublicKeyToken =空’或其依赖项之一。该系统找不到指定的文件。
我认为关键部分是 其依赖项之一 。
好吧,我之前要做 domain.Load(AssemblyName.GetAssemblyName(path));
domain.Load(AssemblyName.GetAssemblyName(path));
foreach (AssemblyName refAsmName in Assembly.ReflectionOnlyLoadFrom(path).GetReferencedAssemblies()) { domain.Load(refAsmName); }
但是FileNotFoundException再次出现在另一个(引用的)程序集上。
如何递归加载所有引用?
加载根程序集之前是否必须创建引用树?如何在不加载程序集的情况下获取其引用?
您需要先调用,CreateInstanceAndUnwrap然后代理对象才能在外部应用程序域中执行。
CreateInstanceAndUnwrap
class Program { static void Main(string[] args) { AppDomainSetup domaininfo = new AppDomainSetup(); domaininfo.ApplicationBase = System.Environment.CurrentDirectory; Evidence adevidence = AppDomain.CurrentDomain.Evidence; AppDomain domain = AppDomain.CreateDomain("MyDomain", adevidence, domaininfo); Type type = typeof(Proxy); var value = (Proxy)domain.CreateInstanceAndUnwrap( type.Assembly.FullName, type.FullName); var assembly = value.GetAssembly(args[0]); // AppDomain.Unload(domain); } } public class Proxy : MarshalByRefObject { public Assembly GetAssembly(string assemblyPath) { try { return Assembly.LoadFile(assemblyPath); } catch (Exception) { return null; // throw new InvalidOperationException(ex); } } }
另外,请注意,如果您使用它,则LoadFrom可能会遇到FileNotFound异常,因为程序集解析器将尝试在GAC或当前应用程序的bin文件夹中查找要加载的程序集。LoadFile而是使用加载任意程序集文件- 但请注意,如果执行此操作,则需要自己加载所有依赖项。
LoadFrom
FileNotFound
LoadFile