Загрузка зависимостей nuget во время выполнения

Я ищу способ запустить код, выполнив следующие шаги:

  • Получение списка пакетов NuGet (список кортежей ( "имя пакета", "версия пакета", "путь к основному классу" ).
  • Получение их в локальном каталоге (пример кода cf # 1)
  • Загрузка их в мою программу во время выполнения
  • Выполнение основных классов путем интроспекции (пример кода 2)

К настоящему времени я борюсь с третьим шагом. Я не могу узнать, как загрузить мой пакет во время выполнения.

Мой главный вопрос:

  • Как узнать, в каких папках были сохранены извлеченные пакеты?
  • Как загрузить содержимое этих каталогов в мою программу?

Спасибо за вашу помощь.

Пример кода №1:

private static void getPackageByNameAndVersion(string packageID, string version)
{
    IPackageRepository repo = 
            PackageRepositoryFactory.Default                          
                  .CreateRepository("https://packages.nuget.org/api/v2");

   string path = "C:/tmp_repo";
   PackageManager packageManager = new PackageManager(repo, path);
   Console.WriteLine("before dl pkg");
   packageManager.InstallPackage(packageID, SemanticVersion.Parse(version));

}

Пример кода # 2:

private static void loadByAssemblyNameAndTypeName(string assemblyName, string typeName)
{
   AppDomain isolationAppDomain = AppDomain.CreateDomain("tmp");
   object a = isolationAppDomain.CreateInstanceAndUnwrap(assemblyName, typeName);
   Type x = a.GetType();
   MethodInfo m = x.GetMethod("Main");
   m.Invoke(a, new object[] { });
}

Ответ 1

Возьмите чашку кофе:)

Загрузка пакета nuget?

Nuget.Core(пакет nuget) - хороший выбор, и вот фрагмент кода, который у меня есть, должен иметь возможность загружать пакет nuget с помощью id и version

var repo = PackageRepositoryFactory.Default
                .CreateRepository("https://packages.nuget.org/api/v2");

string path = "c:\\temp";
var packageManager = new PackageManager(repo, path);
packageManager.PackageInstalled += PackageManager_PackageInstalled;

var package = repo.FindPackage("packageName", SemanticVersion.Parse("1.0.0"));
if (package != null)
{
    packageManager.InstallPackage(package, false, true);
}

Обратите внимание, что я подключил обработчик событий к событию PackageInstalled класса PackageManager.

Как загрузить сборку в изолированном домене приложения?

Поскольку API отражения не предоставляет способ загрузки сборки в определенном домене, мы создадим прокси-класс, который будет действовать как загрузчик в нашем изолированном домене:

public class TypeProxy : MarshalByRefObject
{
    public Type LoadFromAssembly(string assemblyPath, string typeName)
    {
        try
        {
            var asm = Assembly.LoadFile(assemblyPath);
            return asm.GetType(typeName);
        }
        catch (Exception) { return null; }
    }
}

А теперь, как собрать все это?

Здесь идет сложная часть:

private static void PackageManager_PackageInstalled(object sender, 
                                                    PackageOperationEventArgs e)
{
    var files = e.FileSystem.GetFiles(e.InstallPath, "*.dll", true);
    foreach (var file in files)
    {
        try
        {
            AppDomain domain = AppDomain.CreateDomain("tmp");
            Type typeProxyType = typeof(TypeProxy);
            var typeProxyInstance = (TypeProxy)domain.CreateInstanceAndUnwrap(
                    typeProxyType.Assembly.FullName,
                    typeProxyType.FullName);

            var type = typeProxyInstance.LoadFromAssembly(file, "<KnownTypeName>");
            object instance = 
                domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
        }
        catch (Exception ex)
        {
            Console.WriteLine("failed to load {0}", file);
            Console.WriteLine(ex.ToString());
        }

    }
}

Обратите внимание, что этот метод является обработчиком событий, который запускается после загрузки пакета nuget

Также

Обратите внимание, что вам нужно будет заменить <KnownTypeName> на ожидаемое имя типа, исходящее из сборки (или, возможно, запустить обнаружение всех открытых типов в сборке)


Стоит отметить, что я сам не выполнил этот код и не могу гарантировать, что он будет работать из коробки, и все равно может потребоваться некоторая настройка. но, надеюсь, именно эта концепция позволяет вам решить проблему.

Ответ 2

Не делайте этого! Вероятно, вы пытаетесь загрузить nugets на компьютере клиентов, чтобы сэкономить место на дистрибутиве вашего программного обеспечения. Разве это не так?

Общий рекомендуемый подход заключается в загрузке nuget в качестве второго этапа автоматической сборки (после загрузки исходного кода), создания программного обеспечения и запуска автоматических тестов с загруженными nugets. А затем распределите сборку с помощью nugets, которые вы протестировали как сложную целую единицу.