2016-12-01 3 views
3

Использование VS2017 RC, .NET CoreСборка Загрузка в .NET Core

Я пытаюсь загрузить сборку из файла. Зависимости этой сборки находятся в одной папке.

Я использую AssemblyLoadContext.Default.LoadFromAssemblyPath.

Я понимаю, что LoadFromAssemblyPath загружает запрошенную сборку, игнорируя ее зависимости; любая попытка итерации по типам сбоев сбойна с System.Reflection.ReflectionTypeLoadException.

LoaderExceptions содержит список System.IO.FileNotFoundException.

Мне любопытно, почему это так, поскольку все необходимые файлы находятся в одной папке.

Я также попытался загрузить все файлы * .dll в папку, но некоторые из них неожиданно потерпят неудачу с System.IO.FileLoadException.

Что я делаю неправильно?

Редактировать: Я не хочу полагаться на файл .deps (таким образом исключая DependencyContext). Является ли это возможным?

+0

Я не привык к этим типам операций, но вы попробовали позвонить ['Assembly.LoadFrom()'] (https://msdn.microsoft.com/it-it/library/1009fa28 (v = vs. 110) .aspx)? – Phate01

+1

@ Phate01 в .NET Core отсутствует «Assembly.LoadFrom». – Raine

+0

Я думаю, вы должны загружать сборки из GAC, просто указав имя (полное или короткое) сборки, которую вы хотите загрузить. Но это всего лишь предположение. –

ответ

6

Хорошо, что для меня работает, это зарегистрировать дескриптор с событием Resolving и загрузить требуемые сборки по требованию, когда LoadFromAssemblyPath нуждается в зависимостях. Имейте в виду, что это мое решение из часов проб и ошибок, поэтому он может быть не самым идеальным способом. Сейчас это работает для меня. Вот мой код:

AssemblyLoadContext.Default.Resolving += (context, name) => 
    { 
     // avoid loading *.resources dlls, because of: https://github.com/dotnet/coreclr/issues/8416 
     if (name.Name.EndsWith("resources")) 
     { 
      return null; 
     } 

     var dependencies = DependencyContext.Default.RuntimeLibraries; 
     foreach (var library in dependencies) 
     { 
      if (IsCandidateLibrary(library, name)) 
      { 
       return context.LoadFromAssemblyName(new AssemblyName(library.Name)); 
      } 
     } 

     var foundDlls = Directory.GetFileSystemEntries(new FileInfo(<YOUR_PATH_HERE>).FullName, name.Name + ".dll", SearchOption.AllDirectories); 
     if (foundDlls.Any()) 
     { 
      return context.LoadFromAssemblyPath(foundDlls[0]); 
     } 

     return context.LoadFromAssemblyName(name); 
    }; 
} 
private static bool IsCandidateLibrary(RuntimeLibrary library, AssemblyName assemblyName) 
{ 
    return (library.Name == (assemblyName.Name)) 
      || (library.Dependencies.Any(d => d.Name.StartsWith(assemblyName.Name))); 
} 

Бит IsCandidateLibrary() происходит оттуда: http://www.michael-whelan.net/replacing-appdomain-in-dotnet-core/

Я думаю, что вы могли бы пропустить это и весь DependencyContext часть, но она выступает в качестве кэш-памяти и позволяет избежать перегрузки тех же узлов снова и снова. Поэтому я сохранил это.

Смежные вопросы