Watch2–part 6- options
The Watch2 package passes all the command line arguments to the dotnet watch. So how can it have its own settings? Simple: by reading a watch.json file that is in the same folder where it is executing.
1. Testing
I was considering how to perform the testing, and there were two options:
Microsoft File Providers: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/file-providers?view=aspnetcore-8.0
TestableIO: https://github.com/TestableIO/System.IO.Abstractions
I thought that the second option (TestableIO) would be easier to use and more flexible. However, I do not need to test the creation of the file, but rather the content of the file. Therefore, I will use the first option (Microsoft File Providers).
2. Maintain JSON in Sync with C#
I need a solution to transform JSON to C# on the fly (i.e., at compile time). For this, a Roslyn Code Generator can be used. The rscgutils NuGet package will be helpful for this purpose.
Here is the relevant configuration in the project file:
01 02 03 04 05 06 07 08 09 10 11 | < ItemGroup > < PackageReference Include = "Microsoft.Extensions.FileProviders.Abstractions" Version = "8.0.0" /> < PackageReference Include = "rscgutils" Version = "2024.2000.2000" OutputItemType = "Analyzer" ReferenceOutputAssembly = "false" /> </ ItemGroup > < ItemGroup > < ProjectReference Include = "..\Watch2_Interfaces\Watch2_Interfaces.csproj" /> </ ItemGroup > < ItemGroup > < AdditionalFiles Include = "options.gen.json" /> </ ItemGroup > |
Code in Program.cs
The code in Program.cs will utilize the above configurations and packages. Here is an example of how it might look:
This example demonstrates how to read the watch.json file using the Microsoft File Providers package. The rscgutils package will handle the transformation of JSON to C# at compile time, ensuring that the JSON configuration is always in sync with the C# code.
So the code in program.cs will be:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | //test //args = ["run --no-hot-reload"]; //string folder = @"D:\gth\RSCG_Examples\v2\Generator"; //uncomment this line for production string folder = Environment.CurrentDirectory; var serviceCollection = new ServiceCollection(); ConfigureServices(serviceCollection, folder); var serviceProvider = serviceCollection.BuildServiceProvider(); var console = serviceProvider.GetRequiredService<IConsoleWrapper>(); var processManager = serviceProvider.GetRequiredService<ProcessManager>(); var startInfo = serviceProvider.GetRequiredService<IProcessStartInfo>(); var fileOptions = serviceProvider.GetRequiredService<IOptionsReader>(); if (!fileOptions.ExistsFile()) { var file = Path.Combine(folder, "watch2.json" ); File.WriteAllText(file, MyAdditionalFiles.options_gen_json); } await processManager.StartProcessAsync(args, console, startInfo); void ConfigureServices(IServiceCollection services, string folder) { services.AddSingleton<IFileProvider>( new PhysicalFileProvider(folder)); services.AddSingleton<IOptionsReader, OptionsReader>(); services.AddSingleton<Ioptions_gen_json>(it => { var optionsReader = it.GetRequiredService<IOptionsReader>(); return optionsReader.GetOptions() ?? options_gen_json.Empty; }); services.AddSingleton<IConsoleWrapper, ConsoleWrapper>(); services.AddSingleton<ProcessManager, ProcessManager>(); services.AddSingleton<IProcessStartInfo>(provider => new ProcessStartInfoWrapper { FileName = "dotnet" , Arguments = "watch " + string .Join( ' ' , args), WorkingDirectory = folder, RedirectStandardOutput = true , RedirectStandardInput = true , RedirectStandardError = true , UseShellExecute = false , CreateNoWindow = true }); services.AddLogging(loggingBuilder => { loggingBuilder.ClearProviders(); loggingBuilder.SetMinimumLevel(LogLevel.Trace); loggingBuilder.AddNLog( "nlog.config" ); }); services.AddSingleton<ILogger<ProcessManager>, Logger<ProcessManager>>(); services.AddSingleton<Func<IProcessStartInfo, IProcessWrapper>>(it => new ProcessWrapper(it)); } |
Leave a Reply