自定义AppDomain和PrivateBinPath

Ahm*_*lal 9 c# appdomain appdomainsetup

我正在使用c#4.0和一个仅用于测试的控制台应用程序,以下代码确实给出了异常.

AppDomainSetup appSetup = new AppDomainSetup()
{
    ApplicationName = "PluginsDomain",
    ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
    PrivateBinPath = @"Plugins",
    ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
};

AppDomain appDomain = AppDomain.CreateDomain("PluginsDomain", null, appSetup);

AssemblyName assemblyName = AssemblyName.GetAssemblyName(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins", "sample.dll"));

Assembly assembly = appDomain.Load(assemblyName); //This gives an exception of File not found

AppDomain.Unload(appDomain);
Run Code Online (Sandbox Code Playgroud)

在我创建的AppDomain上使用Load时,我一直收到File not found异常.

谢谢.

Mik*_*Two 9

首先确保插件是AppDomain基本路径的子目录.PrivateBinPath仅适用于此处所述的子目录

如果这不是问题,那么看看你的融合绑定日志.使用融合日志查看器还有一个很好的博客帖子.融合日志将告诉您搜索程序集的位置.这应该告诉您路径是否包含在搜索中.

其他可能性之一是它找到你的程序集而不是它的依赖项之一.融合日志查看器再次告诉您.

  • "PrivateBinPath只能在子目录上运行" - *这就是为什么这个糟糕的东西不起作用.谢谢你,谢谢你,谢谢你. (3认同)

Mat*_*Dev 7

尝试从bin目录之外的目录动态加载dll文件时,我遇到了这个线程.长话短说,我能够通过使用该AppDomain.CurrentDomain.AssemblyResolve事件来实现这一目标.这是代码:

//--begin example:

public MyClass(){
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}

private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    foreach (var moduleDir in _moduleDirectories)
    {
        var di = new DirectoryInfo(moduleDir);
        var module = di.GetFiles().FirstOrDefault(i => i.Name == args.Name+".dll");
        if (module != null)
        {
            return Assembly.LoadFrom(module.FullName);
        }
    }
    return null;
}

//---end example
Run Code Online (Sandbox Code Playgroud)

CurrentDomain_AssemblyResolve每次调用方法时都会调用该AppDomain.CurrentDomain.Load("...")方法.此自定义事件处理程序使用您自己的自定义逻辑来执行定位程序集的任务(这意味着您可以将其指向任何位置,甚至在bin路径之外等).我希望这能节省几个小时......

  • 上面的代码不能按原样工作,因为“args.Name”是所需程序集的完全限定名称,而“i.Name”将为您提供文件名。当您从上面复制粘贴(并在代码中修补它)时,请记住这一点。最简单的方法可能是匹配 `args.Name.Split(',')[0] + ".dll"` (2认同)

Ahm*_*lal 5

我想我已经弄清楚为什么会发生这种情况,那是因为当前域也需要加载程序集,即使你在不同的应用程序域中加载程序集,当前域需要知道它并加载它,那是因为如何.NET的设计.

点击此处了解详情.

http://msdn.microsoft.com/en-us/library/36az8x58.aspx

当我检查了融合日志时,我发现新创建的应用程序域成功地能够从私有bin路径加载程序集,以及为什么你仍然得到"File not found"的例外,因为这个异常最初属于到当前的应用程序域.

这意味着如果您将程序集复制到当前应用程序路径或当前域探测的路径,您会发现可以将程序集加载到自定义域中.

希望有所帮助.

  • “此方法只能用于将程序集加载到当前应用程序域中。提供此方法是为了方便无法调用静态 Assembly.Load 方法的互操作调用者。” 你这样做是错的。您应该跨 AD 屏障注入一个类,并让该类使用 Assembly.Load 或 Assembly.LoadFrom 加载程序集。您不妨完全放弃其他应用程序域,因为您没有将程序集与执行的应用程序域隔离。 (2认同)
  • 威尔是对的。您应该调用“appDomain.CreateInstanceAndUnwrap”之类的方法来创建一个继承自新域上的“MarshalByRefObject”的对象并返回一个代理。然后您可以使用该代理,就像它是在您的主域上创建的普通对象一样。如果该对象具有“LoadTheNecessaryAssemblies”方法,如果您从主域上的代理调用该方法,因为该方法将真正在您的新域上运行,您将在新域中加载必要的程序集。 (2认同)