{"id":25685674,"url":"https://github.com/peteraritchie/consoleapplicationbuilder","last_synced_at":"2025-09-03T13:10:09.977Z","repository":{"id":271945058,"uuid":"915026511","full_name":"peteraritchie/ConsoleApplicationBuilder","owner":"peteraritchie","description":"An .NET application builder for use with console applications","archived":false,"fork":false,"pushed_at":"2025-04-13T15:03:52.000Z","size":223,"stargazers_count":36,"open_issues_count":5,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-23T22:08:55.075Z","etag":null,"topics":["console-application","dotnet","dotnet-new","library","nuget-package"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/peteraritchie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-01-10T20:04:18.000Z","updated_at":"2025-04-16T13:42:16.000Z","dependencies_parsed_at":"2025-01-10T23:20:49.680Z","dependency_job_id":"86b7212b-1343-447c-b4a6-49951790d47e","html_url":"https://github.com/peteraritchie/ConsoleApplicationBuilder","commit_stats":null,"previous_names":["peteraritchie/consoleapplicationbuilder"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2FConsoleApplicationBuilder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2FConsoleApplicationBuilder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2FConsoleApplicationBuilder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peteraritchie%2FConsoleApplicationBuilder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/peteraritchie","download_url":"https://codeload.github.com/peteraritchie/ConsoleApplicationBuilder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250522299,"owners_count":21444511,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["console-application","dotnet","dotnet-new","library","nuget-package"],"created_at":"2025-02-24T18:57:09.073Z","updated_at":"2025-04-23T22:09:01.466Z","avatar_url":"https://github.com/peteraritchie.png","language":"C#","readme":"# ConsoleApplicationBuilder\r\n\r\n![Azure DevOps coverage](https://img.shields.io/azure-devops/coverage/Pri/ConsoleApplicationBuilder/18)\r\n![Azure DevOps builds](https://img.shields.io/azure-devops/build/Pri/ConsoleApplicationBuilder/18)\r\n![GitHub Issues or Pull Requests](https://img.shields.io/github/issues-closed/peteraritchie/ConsoleApplicationBuilder)\r\n![GitHub Issues or Pull Requests](https://img.shields.io/github/issues-pr/peteraritchie/ConsoleApplicationBuilder)\r\n\r\nClass library | `dotnet new` project template \r\n:-: | :-:\r\n![NuGet Version](https://img.shields.io/nuget/v/PRI.ConsoleApplicationBuilder) | ![NuGet Version](https://img.shields.io/nuget/v/PRI.ConsoleApplicationBuilder.Templates)\r\n\r\n.NET has had a Dependency Injection (DI) feature for a while. Out-of-the-box generated ASP.NET applications and [console worker project][worker-template] templates create startup code that creates a service collection and service provider (Dependency Injection Container). Developers add their services to the service collection and perform any configuration required.\r\n\r\nExcept for simple console applications.\r\n\r\nSometimes, you just want to create the simplest application to do something very specific. A console application is good for that but doesn't have DI and configuration out of the box. The Console Worker template uses the .NET Generic Host, which does have DI and configuration out of the box. But the Console Worker template implements background worker functionality, which is a bit heavy if you're just trying to do something simple, but with DI support.\r\n\r\nThis is where `ConsoleApplicationBuilder` comes into play.\r\n\r\n`ConsoleApplicationBuilder` provides similar functionality to `WebApplicationBuilder` and `HostApplicationBuilder` by providing the following features:\r\n- Dependency Injection via `IServiceCollection` and `ServiceProvider`.\r\n  - Support for third-party containers via `ConfigureContainer` method.\r\n- Environment-based Configuration supporting the standard .NET conventions:\r\n  - appsettings.json and appsettings.{EnvironmentName}.json\r\n  - Command-line arguments\r\n  - `DOTNET_` environment variable prefix\r\n  - Configuration provider precedence\r\n- Logging\r\n\r\n`ConsoleApplicationBuilder` additionally enables the following .NET features:\r\n  - `IOptions\u003cT\u003e`\r\n\r\nThe accompanying dotnet new project template produces a simple project using `Program` as the type to build and inject with dependencies:\r\n\r\n```csharp\r\nclass Program(ILogger\u003cProgram\u003e logger)\r\n{\r\n    static void Main(string[] args)\r\n    {\r\n        var builder = ConsoleApplication.CreateBuilder(args);\r\n        var program = builder.Build\u003cProgram\u003e();\r\n        program.Run();\r\n    }\r\n\r\n    private void Run()\r\n    {\r\n        logger.LogInformation(\"Hello, World!\");\r\n    }\r\n}\r\n```\r\n\r\nThe above code re-uses `Program` as the class to be instantiated by the service provider and inject with required services. Out of the box, the `Program` constructor requires an `ILogger\u003cProgram\u003e` instance that will be instantiated and injected in the call the `ConsoleApplicationBuilder.Build\u003cT\u003e()`.\r\n\r\nUsing ``ConsoleApplicationBuilder`` can be as minimal as:\r\n\r\n```csharp\r\npublic class Program\r\n{\r\n    public static void Main(string[] args)\r\n    {\r\n        var program = ConsoleApplication.CreateBuilder(args).Build\u003cProgram\u003e();\r\n        program.Run();\r\n    }\r\n\r\n    public void Run()\r\n    {\r\n        // ...\r\n    }\r\n}\r\n```\r\n\r\n## `dotnet new` Project Template\r\n\r\nA dotnet new project template accompanies `ConsoleApplicationBuilder` to quickly generate console applications that support configuration and dependency injection.\r\n\r\nTo install the dotnet new project template:\r\n\r\n```powershell\r\ndotnet new install PRI.ConsoleApplicationBuilder.Templates\r\n```\r\n\r\nThe project template supports many of the established dotnet new console options such as `--TargetFrameworkOverride`, `--Framework`, `--langVersion`, `--skipRestore`, and `--NativeAot`. Top-level statements are not supported because `Program` is used as the default type to instantiate and inject services, requiring an instance constructor. i.e., it acts like `dotnet new console` with the `--use-program-main` argument. \r\n\r\nTo create a console project that supports configuration and dependency injection:\r\n\r\n```powershell\r\ndotnet new consoleapp -o Peter.ConsoleApplication\r\n```\r\n\r\nTo create a console project that supports configuration and dependency injection using C# 9 (and thus not using file-scoped namespaces and primary constructors):\r\n\r\n```powershell\r\ndotnet new consoleapp -o Peter.ConsoleApplication --langVersion 9\r\n```\r\n\r\n## Injecting Dependencies\r\n\r\nInjecting dependencies with `ConsoleApplicationBuilder` follows the same convention as `WebApplicationBuilder` and `HostApplicationBuilder`: by adding to the builder's `Services` collection. For example, we can use the built-in `AddHttpClient\u003cT\u003e` extension (provided in [Microsoft.Extensions.Http]) to add and configure an `HttpClient` singleton and inject it into our `Program` instance as follows:\r\n\r\n```csharp\r\nclass Program(ILogger\u003cProgram\u003e logger, HttpClient httpClient)\r\n{\r\n    static async Task Main(string[] args)\r\n    {\r\n        var builder = ConsoleApplication.CreateBuilder(args);\r\n        builder.Services.AddHttpClient\u003cProgram\u003e(httpClient =\u003e\r\n        {\r\n            httpClient.BaseAddress = new Uri(\"https://jsonplaceholder.typicode.com\");\r\n        });\r\n        var program = builder.Build\u003cProgram\u003e();\r\n        await program.Run();\r\n    }\r\n\r\n    private async Task Run()\r\n    {\r\n        logger.LogInformation(\"Hello, World!\");\r\n        logger.LogInformation(await httpClient.GetStringAsync(\"todos/3\"));\r\n    }\r\n}\r\n```\r\n\r\n## Configuration\r\n\r\nJust like `HostApplicationBuilder` and `WebApplicationBuilder`, classes that accept a `ConfigurationManager` or `IConfigurationManager` parameter in their construction will be injected with the configuration of the current application. Command-line arguments, appsettings values, and environment variables are accessible via the `IConfigurationManager` object.  For example, if we added some properties to our appesettings:\r\n\r\n```json\r\n{\r\n  \"Logging\": {\r\n    \"LogLevel\": {\r\n      \"Default\": \"Information\",\r\n      \"Microsoft.Hosting.Lifetime\": \"Information\"\r\n    }\r\n  },\r\n  \"TransientFaultHandlingOptions\": {\r\n    \"Enabled\": true,\r\n    \"AutoRetryDelay\": \"00:00:07\"\r\n  }\r\n}\r\n```\r\n\r\nWe could add an `IConfigurationManager` parameter to our constructor and access the `TransientFaultHandlingOptions.Enabled` property as follows:\r\n\r\n```csharp\r\nclass Program(ILogger\u003cProgram\u003e logger, IConfigurationManager configuration)\r\n{\r\n    static void Main(string[] args)\r\n    {\r\n        var builder = ConsoleApplication.CreateBuilder(args);\r\n        var program = builder.Build\u003cProgram\u003e();\r\n        program.Run();\r\n    }\r\n\r\n    private void Run()\r\n    {\r\n        logger.LogInformation(\"Hello, World!\");\r\n        logger.LogInformation(\"TransientFaultHandlingOptions:Enabled: {isEnabled}\",\r\n            configuration[\"TransientFaultHandlingOptions:Enabled\"]);\r\n    }\r\n}\r\n```\r\n\r\nWith appsettings, typically the [`IOptions\u003cT\u003e`][ioptions-pattern] pattern is used, which `ConsoleApplicationBuilder` enables:\r\n\r\n```csharp\r\nclass Program(ILogger\u003cProgram\u003e logger, IOptions\u003cTransientFaultHandlingOptions\u003e options)\r\n{\r\n    static void Main(string[] args)\r\n    {\r\n        var builder = ConsoleApplication.CreateBuilder(args);\r\n        builder.Services\r\n            .AddOptions\u003cTransientFaultHandlingOptions\u003e()\r\n            .Bind(builder.Configuration.GetSection(nameof(TransientFaultHandlingOptions)));\r\n        var program = builder.Build\u003cProgram\u003e();\r\n        program.Run();\r\n    }\r\n\r\n    private void Run()\r\n    {\r\n        logger.LogInformation(\"TransientFaultHandlingOptions.Enabled: {Enabled}\", options.Value.Enabled);\r\n        logger.LogInformation(\"Hello, World!\");\r\n    }\r\n}\r\n```\r\n\r\nBe sure to add the [Microsoft.Extensions.Options] package to get the `AddOptions` extension method.\r\n\r\n## Support\r\n\r\nIssues may be logged on the [GitHub issues page](https://github.com/peteraritchie/ConsoleApplicationBuilder/issues)\r\n\r\n## References\r\n\r\n- [Default service container replacement](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines#default-service-container-replacement)\r\n- [Options pattern in .NET][ioptions-pattern]\r\n- [Worker services in .NET][worker-template]\r\n\r\n## Architecturally-significant Decisions\r\n- Azure YAML pipeline files will be stored in the root of the repository, in a folder named `.azuredevops\\azure-pipelines`.\r\n- Top-level statements in Program.cs with the dotnet new template are not supported.\r\n\r\n## Scaffolding\r\n\r\nThe initial project and solution were scaffolded as follows:\r\n\r\n```powershell\r\ndotnet new solution -o 'ConsoleApplicationBuilder\\src' -n ConsoleApplicationBuilder\r\ndotnet new gitignore -o 'ConsoleApplicationBuilder\\src'\r\ndotnet new buildprops -o 'ConsoleApplicationBuilder\\src'\r\ndotnet new classlib -n Pri.ConsoleApplicationBuilder -o 'ConsoleApplicationBuilder\\src\\Pri.ConsoleApplicationBuilder' --framework net8.0 --language 'C#'\r\ndotnet sln 'ConsoleApplicationBuilder\\src' add 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\ConsoleApplicationBuilder'\r\ndotnet add 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\ConsoleApplicationBuilder' package 'Microsoft.Extensions.Hosting'\r\ndotnet add 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\ConsoleApplicationBuilder' package 'Microsoft.Extensions.Http'\r\ndotnet new xunit -n Pri.ConsoleApplicationBuilder.Tests -o 'ConsoleApplicationBuilder\\src\\Pri.ConsoleApplicationBuilder.Tests' --framework net8.0 --language 'C#'\r\ndotnet sln 'ConsoleApplicationBuilder\\src' add 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\Tests'\r\ndotnet add 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\Tests' package 'Moq'\r\ndotnet add 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\Tests' reference 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\ConsoleApplicationBuilder'\r\ndotnet add 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\Tests' package 'xunit'\r\ndotnet add 'C:\\Users\\peter\\src\\products\\ConsoleApplicationBuilder\\src\\Tests' package 'xunit.runner.visualstudio'\r\n```\r\n\r\n[worker-template]: https://learn.microsoft.com/en-us/dotnet/core/extensions/workers\r\n[ioptions-pattern]: https://learn.microsoft.com/en-us/dotnet/core/extensions/options\r\n[Microsoft.Extensions.Http]: https://www.nuget.org/packages/Microsoft.Extensions.Http\r\n[Microsoft.Extensions.Options]: https://www.nuget.org/packages/Microsoft.Extensions.Options","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeteraritchie%2Fconsoleapplicationbuilder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeteraritchie%2Fconsoleapplicationbuilder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeteraritchie%2Fconsoleapplicationbuilder/lists"}