0

外部アセンブリのロードを自分で処理する必要がある環境で使用する DLL があります。アセンブリを AppDomain にロードしたいと考えています。CurrentAppDomain でこれを試すと問題なく動作しますが、自分で作成した appdomain でこれを実行すると失敗します。背景は、アセンブリが最後に「解放」されるように、最後に appdomain をアンロードしたいということです。

public ZipEx() 
{
    try
    {
        AppDomainSetup domaininfo = new AppDomainSetup();
        domaininfo.ApplicationBase = System.Environment.CurrentDirectory;
        Evidence adevidence = AppDomain.CurrentDomain.Evidence;

        //THIS CODE WORKS
        //System.AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        //System.AppDomain.CurrentDomain.Load("ICSharpCode.SharpZipLib");

        //THIS CODE DOES NOT WORK
        AppDomain zipDomain2 = AppDomain.CreateDomain("ADZib2", adevidence, domaininfo);
        PolicyLevel polLevel = PolicyLevel.CreateAppDomainLevel();
        PermissionSet permSet = new PermissionSet(PermissionState.Unrestricted);
        permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.AllFlags));
        polLevel.RootCodeGroup.PolicyStatement = new PolicyStatement(permSet);
        zipDomain2.SetAppDomainPolicy(polLevel);
        zipDomain2.AssemblyResolve += CurrentDomain_AssemblyResolve;
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show("ex in ctor" + Environment.NewLine + ex.ToString());
    }
    if (_loadedAssembly == null)
    {
    }
}

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    System.Windows.Forms.MessageBox.Show("CurrentDomain_AssemblyResolve");
    Assembly assembly = null;
    bool foundAssembly = false;

    int idx = args.Name.IndexOf(',');
    if (idx > 0)
    {
        string partialName = args.Name.Substring(0, idx);
        string dllName = partialName + ".dll";

        //Add the directorys where the assembly hould be resolved
        List<string> directorySearch = new List<string>
        {
          string.Format("{0}{1}{2}",Environment.CurrentDirectory,Path.DirectorySeparatorChar, dllName),
          string.Format("{0}{1}{2}",AppPath,Path.DirectorySeparatorChar, dllName)
        };

        foreach (string fileName in directorySearch)
        {
            if (File.Exists(fileName))
            {
                foundAssembly = true;
                assembly = Assembly.LoadFrom(fileName);
                break;
            }
        }

        if (assembly == null)
        {
            if (!foundAssembly)
            {
                foreach (string fileName in directorySearch)
                {
                }
            }
            else
            {
            }
        }
    }
    if (assembly != null) 
    {
        System.Windows.Forms.MessageBox.Show("assembly is not null");
    }
    return assembly;
}

私の質問は、アセンブリをロードするために作成した appdomain をどのように使用するのですか?

4

1 に答える 1

1

あなたの現在の例では、新しく作成された AppDomain がアセンブリを試行してロードする原因となるコメント解除されたコードは見当たりません。この回答では、コメント解除されたコードに欠落している Load への呼び出しがあると想定しています。

AppDomain.Loadのヘルプのコメントによると、現在の AppDomain でのみ使用する必要があります。そうしないと、アセンブリを両方の AppDomains にロードしようとするため、例外が発生する可能性があります。アセンブリを他の AppDomain のみに読み込むには、CreateInstance 関数の 1 つを呼び出す必要があります。この特定のケースでは、タイプだけでなく名前でもアセンブリを指定できるため、 CreateInstanceFromAndUnwrap関数をお勧めします。

インスタンス化して AppDomain の境界を越えてやり取りできる型がない場合 (可能性は低いですが可能です)、これを機能させるには、列挙型や構造体などの単純な型を作成して破棄する必要がある場合があります。

于 2015-01-28T15:00:33.973 に答える