AppDomain探测问题

时间:2012-11-24 06:07:19

标签: c# .net appdomain

我正在尝试使用以下代码将位于用户定义位置的强名称程序集加载到AppDomain中:

    AppDomainSetup ads1 = new AppDomainSetup();
    if (ads1.PrivateBinPath != null)
    {
        ads1.PrivateBinPath += ads1.PrivateBinPath.Length == 0 ? "" : Path.PathSeparator.ToString();
    }
    ads1.PrivateBinPath += @"c:\work\abc1";
    sandbox1 = AppDomain.CreateDomain("sandbox1", null, ads1);
    Object o1 = sandbox1.CreateInstanceFromAndUnwrap(@"abc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f10808f3df0adc34", "Abc.Def");

当我跑步时,我收到此错误:

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'file:///C:\Users\gel\Documents\Visual Studio 2012\Projects\ConsoleApplicat
ion1\ConsoleApplication1\bin\Debug\abc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f10808f3df0adc34' or one of its dependencies. The system cannot find the fil
e specified.
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stack
Mark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& st
ackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& st
ackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boole
an forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.LoadFrom(String assemblyFile, Evidence securityEvidence)
   at System.Activator.CreateInstanceFromInternal(String assemblyFile, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, C
ultureInfo culture, Object[] activationAttributes, Evidence securityInfo)
   at System.AppDomain.CreateInstanceFrom(String assemblyFile, String typeName)
   at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName)
   at System.AppDomain.CreateInstanceFromAndUnwrap(String assemblyName, String typeName)
   at ConsoleApplication1.Program.Main(String[] args) in c:\Users\gel\Documents\Visual Studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\Program.cs:li
ne 69

就好像AppDomain根本没有查看PrivateBinPath。我做得不对劲?我在Explorer窗口中双重检查,我可以看到我在PrivateBinPath中指定的位置的程序集。如果我只是执行Assembly.LoadFile并指定正确的路径,那就行了,但这样做会破坏尝试将其加载到另一个AppDomain中的目的。

2 个答案:

答案 0 :(得分:2)

我修改了你的代码,这很有用。查看您需要完成的更改。

        AppDomainSetup ads1 = new AppDomainSetup();
        if (ads1.PrivateBinPath != null)
        {
            ads1.PrivateBinPath += ads1.PrivateBinPath.Length == 0 ? "" : Path.PathSeparator.ToString();
        }
        ads1.PrivateBinPath += @"D:\ConsoleApplication1\ClassLibrary1\bin\debug";
        AppDomain sandbox1 = AppDomain.CreateDomain("sandbox1", null, ads1);
        Object o1 = sandbox1.CreateInstanceFromAndUnwrap(@"ClassLibrary1.dll", "ClassLibrary1.Class1");

答案 1 :(得分:1)

我相信它无法将该程序集加载到您当前的AppDomain中,而不是加载到新的程序集中(它可能会加载好)。

这种行为有时称为“泄漏类型到另一个域”,并试图直接使用创建的对象。要解决这个问题,需要在另一个AppDomain中完全创建类(即通过运行一些处理创建的自定义代码),而不是仅暴露两个域都知道的接口/类。查看Unloadable plugins了解详情。

本文采用的代码的一小部分 - 在CreateInstanceFromAndUnwrap的其他AppDomain中创建RemoteLoader类,并使用该对象加载/管理新AppDomain中的其他类型。

public class RemoteLoader : MarshalByRefObject
{ 
    public void Load(string assemblyName, string typeName)
    {
        object instance = Activator.CreateInstance(assemblyName, typeName);
        //Do something with instance, or return shared interface of it.
    }
}

旁注:除非您出于教育目的而考虑使用现有的插件框架,例如MEF