如何使用递归的所有引用将程序集加载到 AppDomain? [英] How to Load an Assembly to AppDomain with all references recursively?

查看:32
本文介绍了如何使用递归的所有引用将程序集加载到 AppDomain?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将一些具有复杂引用树的程序集加载到新的 AppDomain(MyDll.dll -> Microsoft.Office.Interop.Excel.dll -> Microsoft.Vbe.Interop.dll-> Office.dll -> stdole.dll)

I want to load to a new AppDomain some assembly which has a complex references tree (MyDll.dll -> Microsoft.Office.Interop.Excel.dll -> Microsoft.Vbe.Interop.dll -> Office.dll -> stdole.dll)

据我所知,当一个程序集被加载到 AppDomain 时,它的引用不会自动加载,我必须手动加载它们.所以当我这样做时:

As far as I understood, when an assembly is being loaded to AppDomain, its references would not be loaded automatically, and I have to load them manually. So when I do:

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:

无法加载文件或程序集MyDll,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"或其依赖项之一.系统找不到指定的文件.

Could not load file or assembly 'MyDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

我认为关键部分是其依赖项之一.

好的,我在 domain.Load(AssemblyName.GetAssemblyName(path));

foreach (AssemblyName refAsmName in Assembly.ReflectionOnlyLoadFrom(path).GetReferencedAssemblies())
{
    domain.Load(refAsmName);
}

但是在另一个(引用的)程序集上再次遇到 FileNotFoundException.

But got FileNotFoundException again, on another (referenced) assembly.

如何递归加载所有引用?

How to load all references recursively?

在加载根程序集之前是否必须创建引用树?如何在不加载的情况下获取程序集的引用?

Do I have to create references tree before loading root assembly? How to get an assembly's references without loading it?

推荐答案

您需要先调用 CreateInstanceAndUnwrap,然后您的代理对象才会在外部应用程序域中执行.

You need to invoke CreateInstanceAndUnwrap before your proxy object will execute in the foreign application domain.

 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 来加载任意程序集文件——但请注意,如果你这样做,你需要自己加载任何依赖项.

Also, note that if you use LoadFrom you'll likely get a FileNotFound exception because the Assembly resolver will attempt to find the assembly you're loading in the GAC or the current application's bin folder. Use LoadFile to load an arbitrary assembly file instead--but note that if you do this you'll need to load any dependencies yourself.

这篇关于如何使用递归的所有引用将程序集加载到 AppDomain?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆