3

カスタムの場所から dll を動的にロードする次のコードを見つけました。

private void Form1_Load(object sender, EventArgs e)
{
    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
}

private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
    string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    string assemblyPath = Path.Combine(folderPath, "libs", new AssemblyName(args.Name).Name + ".dll");
    if (File.Exists(assemblyPath) == false) return null;
    Assembly assembly = Assembly.LoadFrom(assemblyPath);
    return assembly;
}

private void button1_Click(object sender, EventArgs e)
{
    var zip = ZipFile.Read("test.zip");

    foreach (ZipEntry file in zip)
    {
        file.Extract(".", ExtractExistingFileAction.OverwriteSilently);
    }
}

場合によっては、このソリューションが機能しますが、ZipDotNet dll を使用すると、次のようになります。

InnerException  {"File or assembly name \"Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c\" or one of its dependencies, was not found. Operation is not supported. (Exception from HRESULT: 0x80131515)":"Ionic.Zip, Version=1.9.1.8, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c"}   System.Exception {System.IO.FileLoadException}


通過してからif (File.Exists(assemblyPath) == false) return null;、Ionic.Zip.dll の依存関係をロードする際の問題だと思いますか? それらもどのように解決しますか?

4

1 に答える 1

4

ここで Iconic.Zip.dll のソース コードを見ると、プロジェクト内の唯一の参照は System、System.Data、System.Security、および System.Xml であることがわかります。その参照をロードします。

あなたのアセンブリ解決方法は少し単純すぎると思います。アセンブリ名がファイル名と同じであると想定していますが、常にそうであるとは限りません。したがってAssemblyName、ターゲット フォルダ内の各 dll を取得し、名前とファイルのマッピングを保存することができます。次に、リゾルバーが名前を要求すると、既知の名前でそれを検索し、アセンブリ ファイルをロードします。これがアイデアの簡単な実装です。

private Dictionary<string, string> assemblyNameToFileMapping = new Dictionary<string, string>();

private void Form1_Load(object sender, EventArgs e)
{
    GetAssemblyNames();
    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
}

private void GetAssemblyNames()
{
  string folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "libs");
  foreach(string file in Directory.EnumerateFiles(folderPath, "*.dll"))
  {
     try
     {
         AssemblyName name = AssemblyName.GetAssemblyName(file);
         assemblyNameToFileMapping.Add(name.FullName, file);
     }
     catch { } // Just move on if we can't get the name.
  }
}

private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
    string file;
    if (assemblyNameToFileMapping.TryGetValue(args.Name, out file))
    {
       return Assembly.LoadFrom(file);
    }
    return null;
}
于 2013-03-19T08:46:32.380 に答える