1

我正在尝试使用以下代码将位于用户定义位置的强命名程序集加载到 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 中查找。我做错了什么?我在资源管理器窗口中进行了双重检查,我可以在 PrivateBinPath 中指定的位置看到程序集。如果我只执行 Assembly.LoadFile 并指定正确的路径,它就可以正常工作,但这会破坏尝试将其加载到另一个 AppDomain 的目的。

4

2 回答 2

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");
于 2012-11-24T08:37:54.637 回答
1

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

这种行为有时称为“将类型泄漏到另一个域”,是由于尝试直接使用创建的对象而引起的。要解决这个问题,需要在另一个 AppDomain 中完全创建类(即通过运行一些处理创建的自定义代码),而不是只公开两个域都知道的接口/类。查看可卸载插件了解详情。

本文采用的一小部分代码 - 在其他 AppDomain 中创建 RemoteLoader 类,CreateInstanceFromAndUnwrap并使用该对象在新 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

于 2012-11-24T06:33:39.337 回答