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

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

  1. получение списка пакетов NuGet (список кортежей ("имя пакета"," версия пакета","путь к основному классу").
  2. получение их в локальном каталоге (пример кода cf #1)
  3. загрузка их в мою программу во время выполнения
  4. запуск основных классов путем интроспекции (пример кода cf #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[] { });
}

2 ответов


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

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

NuGet для.Core (NuGet package) - хороший выбор, и вот фрагмент кода, который у меня есть, который должен иметь возможность загрузить пакет 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 класса.

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

С reflection 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> с ожидаемым именем типа, поступающим из сборки (или, возможно, запустить обнаружение всех открытых типов в сборке)


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


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

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