I am building a job-running system that has one .NET Core console app as a job runner, and user-extensible jobs - users can reference my NuGet package, write a class that extends my Job type, and implement the Execute method. I want to provide all the console logic in the NuGet package such that referencing it will allow for building a ready-to-run console app. I've been able to use NuGet to publish the required build targets to build the app, but I'm looking for a way to actually load the job dll.
My current solution is:
I would like to avoid step 1, which I believe I would be able to do if the NuGet package simply provided an entry point for a console app. Is it possible to either build a console app without an entry point and supply it via NuGet, or use a class library and have all the requisite dlls loaded in one appdomain?
If I correctly understdood you have following projects:
Currently Jobs are referencing JobTypeBaseClass and Runner using reflection execute work defined in it. This is the correct and wide known approach.
But what I understood your target is to give developers which will be creating the jobs very easily way of starting work. So they should reference the nuget and just like it it should work.
Answering your question: It is not possible to build console app without entry point so without static Main method. But this requirement can be used by you. In the nuget file you can add Install script which will change Main method of the Program.cs file and add line which will invoke required code.
This way after installing nuget job will work. Of course it won't do anything.
So your nuget should:
How much effort are you willing to go to for this?
The way that Windows knows where the entry point for an executable is in the AddressOfEntryPoint field of the _IMAGE_OPTIONAL_HEADER structure in the PE header of the file. I'm not an expert, but I believe that the dotnet CLI uses this as well. Since the AddressOfEntryPoint field is simply a byte offset in the file, it's impossible to have the entry point in a different file.
One way it could work (I haven't tested) is if your job runner is an exe, not a dll, within the nupkg. That way when each job builds (and if necessary using the dotnet cli, also published), the output folder will contain the job runner exe that is run. The job itself can then be a dll, so that it doesn't need its own entry point. But your job runner will still need to use reflection to load all assemblies, which I agree is a bad idea. It also prevents dotnet run
from working on the job task project, which makes debugging much harder for people implementing jobs.
Another option is just to tell job task implementors to include a one line Main method in their exe
public static void Main()
{
JobRunner.Run();
}
This also requires the JobRunner to use reflection to find jobs, but at least you could use Assembly.GetCallingAssembly()
or Assembly.GetEntryAssembly()
to avoid loading all dlls. You could change JobRunner.Run()
to JobRunner.Run(Type)
, or JobRunner.Run<T>() where T : IJob
so the job implementors tell the job runner exactly which job to run in their own Main method and avoid step 2 in your job runner. It's similar to how ASP.NET Core applications have a similar, if not identical, Program.Main, so it's not exactly unprecedented.
If you want to make it as easy as possible for your job implementors, you could take inspiration in how .NET Core creates temporary .cs files in the obj/$(Configuration)/
folders. Create your nuget package with the appropriate msbuild .targets file and have your custom msbuild target file create another temporary .cs file in the obj file, which contains the Main() entry point, and have the .cs file included for compilation.
For extra credit, you could use Roslyn to analyse all the non-temporary .cs files in the project, find all the jobs, then in your generated .cs file call your JobRunner's Main method with the type(s) detected, so at run time it doesn't need to use reflection to do step 2.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.