Как получить точку входа в программу .NET Core в пакете NuGet, на который она ссылается? - PullRequest
0 голосов
/ 22 октября 2018

Я создаю работающую систему, в которой одно приложение консоли .NET Core используется для выполнения заданий, а задания, расширяемые пользователем, - пользователи могут ссылаться на мой пакет NuGet, писать класс, расширяющий тип моего задания, и реализовывать Execute.метод.Я хочу предоставить всю консольную логику в пакете NuGet так, чтобы ссылка на нее позволила создать готовое к запуску консольное приложение.Я смог использовать NuGet для публикации необходимых целей сборки для сборки приложения, но я ищу способ на самом деле загрузить работу DLL.

Мое текущее решение:

  1. Job-runner загружает все dll в своем рабочем каталоге с помощью отражения
  2. Job-runner проверяет все эти dll на предмет того, который реализует требуемый тип
  3. Job-runner создает экземпляртип задания и выполняет задание

Я бы хотел избежать шага 1, что, я полагаю, я смог бы сделать, если бы пакет NuGet просто предоставил точку входа для консольного приложения.Можно ли либо создать консольное приложение без точки входа и предоставить его через NuGet, либо использовать библиотеку классов и загрузить все необходимые библиотеки в один домен приложения?

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Сколько усилий вы готовы приложить для этого?

Способ, которым Windows знает, где находится точка входа для исполняемого файла, в поле AddressOfEntryPoint структуры _IMAGE_OPTIONAL_HEADER вPE заголовок файла.Я не эксперт, но я считаю, что Dotnet CLI также использует это.Поскольку поле AddressOfEntryPoint является просто байтовым смещением в файле, невозможно иметь точку входа в другом файле.

Один способ, которым это может работать (я не проверял), - это если ваш исполнитель заданий являетсяОтлично, не dll, внутри nupkg.Таким образом, когда каждое задание создается (и, если необходимо, с помощью dotnet cli, также публикуемого), выходная папка будет содержать исполняемый файл исполняемого задания.Само задание может быть dll, поэтому ему не нужна собственная точка входа.Но вашему руководителю работы все равно нужно будет использовать отражение для загрузки всех сборок, что, я согласен, является плохой идеей.Он также не позволяет dotnet run работать над проектом рабочих задач, что значительно усложняет отладку для людей, реализующих рабочие места.

Другой вариант - просто сказать разработчикам рабочих задач включить однострочный метод Main в их exe

public static void Main()
{
  JobRunner.Run();
}

Для этого также требуется, чтобы JobRunner использовал рефлексию для поиска работы, но по крайней мере вы могли бы использовать Assembly.GetCallingAssembly() или Assembly.GetEntryAssembly(), чтобы избежать загрузки всех библиотек.Вы можете изменить JobRunner.Run() на JobRunner.Run(Type) или JobRunner.Run<T>() where T : IJob, чтобы разработчики заданий сообщали исполнителю заданий, какое именно задание следует запускать в своем собственном методе Main, и избегайте выполнения шага 2 в задании.Это похоже на то, как приложения ASP.NET Core имеют аналогичный, если не идентичный, Program.Main, так что это не совсем беспрецедентно.

Если вы хотите максимально упростить процесс реализации ваших заданий, вы могли быВдохновитесь тем, как .NET Core создает временные файлы .cs в папках obj/$(Configuration)/.Создайте свой пакет nuget с соответствующим файлом msbuild .targets и попросите ваш пользовательский целевой файл msbuild создать другой временный файл .cs в файле obj, который содержит точку входа Main (), и иметь файл .csвключены для компиляции.

Для дополнительного кредита вы можете использовать Roslyn для анализа всех не временных файлов .cs в проекте, найти все задания, а затем в созданном вами файле .cs вызвать метод Main вашего JobRunner с помощьюобнаруженный тип (типы), поэтому во время выполнения не нужно использовать отражение для выполнения шага 2.

0 голосов
/ 23 октября 2018

Если я правильно понимаю, у вас есть следующие проекты:

  • Runner - используется для выполнения заданий
  • JobTypeBaseClass - общий класс, который может использоваться заданиями (определенными ниже) иRunner
  • Задания - задачи, выполняющие работу, определенную разными разработчиками

enter image description here

В настоящее время задания ссылаются на JobTypeBaseClass и Runnerс помощью отражения выполнить заданную в нем работу. Это правильный и широко известный подход.

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

Отвечая на ваш вопрос: невозможно создать консольное приложение без точки входа, поэтому без статического метода Main.Но это требование может быть использовано вами.В файле nuget вы можете добавить скрипт установки, который изменит метод Main файла Program.cs, и добавит строку, которая вызовет необходимый код.

Таким образом, после установки работы nuget будет работать.Конечно, это ничего не сделает.

enter image description here

Таким образом, ваш nuget должен:

  • содержать JobTypeBaseClass
  • содержать скрипт, который создаст новое заданиеФайл .cs, который будет классом, реализующим базу из JobTypeBaseClass
  • , содержит скрипт, который изменит метод Main в Program.cs, который вызовет метод, созданный выше.
...