Zum Hauptinhalt springen

AddSingleton() vs AddScoped() vs AddTransient()

AddSingleton

AddSingleton() - our 2 services point to the same Singleton

  • one gets mutated -> all do.

AddScoped

AddScoped() - The Services gets created (then destroyed) for EVERY HTTP Request

  • so no persistence between requests.
  • BUT service1 == service2 both again point to the same 'singleton'-ish for that lifetime.
  • We could make the private static string[] _stages static to persists the service.instance lifetimes.
    • then the Plants would increase agai

AddTransient

AddTransient() - our 2 services are Separate

  • again no persistence between requests. Lifetime coupled to Http-Request.
  • one gets mutated then destroyed without touching the other.

Example

  • Programm.cs
// inject our Services:
// Singleton() - our 2 services point to the same Singleton
// - one gets mutated -> all do.
// builder.Services.AddSingleton<IPlantService, PlantService>();

// Scoped() - The Services gets created (then destroyed) for EVERY HTTP Request
// - so no persistence between requests.
// - BUT service1 == service2 both again point to the same 'singleton'-ish for that lifetime.
// - We could make the `private static string[] _stages` **static** to persists the service.instance lifetimes.
// - then the Plants would increase again.
// builder.Services.AddScoped<IPlantService, PlantService>();

// Transient() - our 2 services are Separate
// - again no persistence between requests. Lifetime coupled to Http-Request.
// - one gets mutated then destroyed without touching the other.
builder.Services.AddTransient<IPlantService, PlantService>();

  • Controllers/PlantController.cs
using Microsoft.AspNetCore.Mvc;
using tutorials.Models;
using tutorials.Services.PlantService;

namespace tutorials.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PlantController : ControllerBase
{
private readonly IPlantService _plantService1;
private readonly IPlantService _plantService2;

public PlantController(IPlantService s1, IPlantService s2)
{
_plantService1 = s1;
_plantService2 = s2;
}

[HttpGet("count")]
public ActionResult<int> GetPlantsCount()
{
return _plantService2.GetPlantsCount();
}

[HttpGet]
public ActionResult<List<Plant>> GetPlantsList()
{
return _plantService2.GetPlantsList();
}

[HttpPost]
public ActionResult<List<Plant>> Grow()
{
_plantService1.GrowRandomPlant();
return _plantService2.GetPlantsList();
}
}
}
  • Services/PlantService/PlantService.cs
using tutorials.Models;

namespace tutorials.Services.PlantService;

/// <summary>
/// Some basic Service that grows Trees and returns data about the Trees
/// </summary>
public class PlantService : IPlantService
{
private static string[] _stages = { "Seed", "Germination", "Sapling", "Mature Tree", "Dying Tree", "Fire Wood", };

public List<Plant> PlantsList = new()
{
new Plant(){ Stage = _stages[0]},
new Plant(){ Stage = _stages[0]},
new Plant(){ Stage = _stages[2]},
};

public int GetPlantsCount()=> PlantsList.Count;

public List<Plant> GetPlantsList() => PlantsList;

public void GrowRandomPlant()
{
PlantsList.Add(new Plant
{
Stage = _stages[new Random().Next(_stages.Length)]
});
}
}
  • Services/PlantService/IPlantService.cs
using tutorials.Models;
namespace tutorials.Services.PlantService;

// interface because we want to inject it to show different ways of doing so
public interface IPlantService
{
int GetPlantsCount();
List<Plant> GetPlantsList();
void GrowRandomPlant();
}