Dependency injection in .NET Core

Dependency injection is native-available in .NET Core

DI implementation

interface we want to inject

public interface IDateTime
{
	DateTime Now { get; }
}

interface’s implementation

public class SystemDateTime : IDateTime
{
	public DateTime Now
	{
		get { return DateTime.Now; }
	}
}

service we inject into

public class HomeController : Controller
{
	private readonly IDateTime _dateTime;

	public HomeController(IDateTime dateTime)
	{
		_dateTime = dateTime;
	}

	public IActionResult Index()
	{
		var serverTime = _dateTime.Now;
		return Ok(serverTime);
	}
}

Configuration: We have to register our DI services into startup.cs

public class Startup
{

	public IConfiguration Configuration { get; }
	

	public Startup(IConfiguration configuration)
	{
		Configuration = configuration
	}

	public void ConfigureServices(IServiceCollection services)
	{
		// add dependencies here
		services.AddSingleton<IDateTime, SystemDateTime>();
	}

}

Services lifetime types

Check this SO answer

  • scoped: objects are the same for a given request, but differ across each new request (think of a shared class. A class that’s called in multiple other classes. Each parent-class would share the same child-class instance)
  • transient: objects are always different. they’re created each time they’re called (each parent-class would’ve an unique child-class instance)
  • singleton: objects are always the same for every request

(!) We have to be careful. If we put an object with a shorter lifetime inside a longer living object, the inner object would only be created once. (think a transient or scoped dependency inside a singleton). (!)
The other way around is OK. You can put a singleton dependency inside a transient or scoped with no problem.

Examples on when to use each one

  • scoped: (created once per request) we may use this for a SQL connection. It will create and dispose the SQL connection per request.
  • transient: (created each time they’re requested from the service container) For example, for an HttpClient service. We want this service to create a new HttpClient every time we send a request, so we don’t reuse the same old one.
  • singleton: normally used for a global single instance. For example, you if you have an image store service, you could have a service to load images from a given location and keep them in memory for future use.

Injection with FromServices

This enables injection directly into an action method without using constructor injection.

public IActionResult About([FromServices] IDateTime dateTime)
{
	return Content($"current server time: {dateTime.Now}");
}

Reference(s)

https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-8.0#action-injection-with-fromservices
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0#service-lifetimes
https://stackoverflow.com/questions/67206763/when-to-use-following-transient-scoped-and-singleton