user2818430
user2818430

Reputation: 6029

ASP.NET Core access other services using dependency injection

This is an ASP.NET Core default project ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

My question is how can I access the email service or sms service inside ApplicationDbContext?

Or let's say I will have a custom service built and I register it in the DI like this:

services.AddTransient<ICustomService, CustomService>();

how can I access email service or sms service inside of this?

I assume that the email and sms service must be added to the DI before other services that will use them right?

Upvotes: 2

Views: 4837

Answers (1)

Set
Set

Reputation: 49789

Default DI implementation provided with ASP.NET Core supports only constructor injection. Your CustomService class should have ctor that expects dependencies (SMS/Email senders) as parameters:

public class CustomService : ICustomService
{
    public ClassName(IEmailSender emailSender, ISmsSender smsSender)
    {
        // use senders here or store in private variables
    }
}

When you define constructor, note that (from Constructor Injection Behavior section)

  • Constructor injection requires that the constructor in question be public.
  • Constructor injection requires that only one applicable constructor exist. Constructor overloads are supported, but only one overload can exist whose arguments can all be fulfilled by dependency injection.
  • Constructors can accept arguments that are not provided by dependency injection, but these must support default values.

I assume that the email and sms service must be added to the DI before other services that will use them right?

They should be registered in DI container before it will try to construct the first instance of the class that expects it as constructor arguments. As method services.AddTransient<ICustomService, CustomService>(); doesn't instantiate CustomService class, the following it still a valid code:

services.AddTransient<ICustomService, CustomService>();
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();

But it is a good practice to register in order from simple to complicated type.

Upvotes: 6

Related Questions