user2715109
user2715109

Reputation: 351

How do you use dependency injection in an asp.net console app?

I am doing something like:

        private static  IServiceProvider serviceProvider;

    public Program(IApplicationEnvironment env, IRuntimeEnvironment runtime)
    {
        var services = new ServiceCollection();
        ConfigureServices(services);
        serviceProvider = services.BuildServiceProvider();

        // Set up configuration sources.
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }
    public IConfigurationRoot Configuration { get; set; }

    private void ConfigureServices(IServiceCollection services)
    {
        //Console.WriteLine(Configuration["Data:DefaultConnection:ConnectionString"]);

        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<DbContext>(options =>
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
    }

I am struggling to get to use the program using an injected DbContext. Any idea? How do you instantiate the program and get everything injected? I don't know what to do in the static Main method.

Is there an equivalent for this?

public static void Main(string[] args) => WebApplication.Run<Startup>(args);

Something like?

public static void Main(string[] args) => ConsoleApplication.Run<Program>(args);

Upvotes: 1

Views: 6591

Answers (2)

user7136793
user7136793

Reputation:

Just in case anyone else is looking for a small and simple example to follow.

Here is a small console app I wrote recently for a an example. It"s only a small password generator demonstration of DI in an app with unit tests.

https://github.com/AnthonySB/PasswordApplication

using System;
using Microsoft.Extensions.DependencyInjection;
using PasswordExercise.Interfaces;
using PasswordExercise.Services;

namespace PasswordExercise
{
    class Program
    {
        static void Main(string[] args)
        {
            //Dependency injection
            var serviceProvider = new ServiceCollection()
                .AddSingleton<IPasswordGeneratorService, PasswordGenerator>()
                .AddSingleton<IPasswordService, PasswordService>()
                .BuildServiceProvider();

            //Get the required service
            var passwordService = serviceProvider.GetService<IPasswordService>();

            //For reading from the console
            ConsoleKeyInfo key;

            //Display the menu
            passwordService.Menu();

            do
            {
                //Read the console key, do not display on the screen
                key = Console.ReadKey(true);

                switch (key.KeyChar.ToString())
                {
                    case "1":

                        Console.WriteLine("Simple password: {0}", passwordService.SimplePassword());
                        break;
                    case "2":
                        Console.WriteLine("Moderate password: {0}", passwordService.ModeratePassword());
                        break;
                    case "3":
                        Console.WriteLine("Strong password: {0}", passwordService.StrongPassword());
                        break;
                }
            } while (key.Key != ConsoleKey.Escape);
        }
    }
}

Hope this helps someone.

Upvotes: 1

user2715109
user2715109

Reputation: 351

This is how I did it:

public class Startup
{
    public static IConfigurationRoot Configuration { get; set; }

    public static void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<DbContext>(options =>
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

        services.AddSingleton<IMyManager, Manager>();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddSingleton<Program, Program>();
    }

    public static void Main(string[] args)
    {
        var services = new ServiceCollection();
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json");
            .AddEnvironmentVariables()
            .AddUserSecrets();
        Configuration = builder.Build();
        ConfigureServices(services);
        var provider = services.BuildServiceProvider();

        CancellationTokenSource ctSource = new CancellationTokenSource();
        CancellationToken ct = ctSource.Token;

        Task task = Task.Run(async () =>
        {
            Program program = provider.GetRequiredService<Program>();
            await program.Run(ct);
        });
        try
        {
            task.Wait();
        }
        catch (AggregateException e)
        {
            throw e.InnerException;
        }
        ctSource.Cancel();
        ctSource.Dispose();
    }
}

Then the program is just:

class Program
{
    private IMyManager _myManager;

    public Program(IMyManager myManager)
    {
        _myManager = myManager;
    }

    public async Task Run(CancellationToken cancelationToken)
    {
        while (true)
        {
            cancelationToken.ThrowIfCancellationRequested();

            // My things using _myManager

            await Task.Delay(10000, cancelationToken);
        }
    }
}

I deleted a bunch of stuff for the example so it probably crashes somewhere, but you get the idea.

Upvotes: 2

Related Questions