위의 3가지 중 유난히 Transient 와 Scoped 의 차이점을 정확히 이해하기 어려운데요. 여기서 예제를 들어볼 까 합니다.
먼저 DI 를 구성하기 위해 인터페이스와 구현체를 만들어 봅시다.
[IRepositoy] 인터페이스
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Core1.Models
{
public interface IRepository
{
int GetnUpdateCounter();
}
}
[Repositoy] 구현체 클래스
: 여기서 자동증가 값을 구현했습니다. 동일한 인스턴스라면 계속 누적되어 +1 씩 증가되겠죠...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Core1.Models
{
public class MyRepository : IRepository
{
private int i;
public int GetnUpdateCounter()
{
return i++;
}
}
}
Startup.cs 에서 AddScoped 생명주기를 테스트 하기 위해 인스턴스와 구현클래스를 매칭했습니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IRepository, MyRepository>();
services.AddMvc();
}
호출하는 샘플을 보여주기 위해서 TagHelper 를 만들어 봤습니다.
: View 단에서 <test message="test"></test> 이런식으로 구현할 예정입니다. 실행하면 h5 태그로 구성되며 내용은 message : 증가값 이 출력됩니다.
using Core1.Models;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Core1.TagHelpers
{
public class TestTagHelper : TagHelper
{
private readonly IRepository _myRepository;
public TestTagHelper(IRepository myRepository)
{
_myRepository = myRepository;
}
public string Message { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "h5";
output.Content.SetContent(Message + " : " + _myRepository.GetnUpdateCounter().ToString());
}
}
}
home 컨트롤러를 구현합니다. DI 를 위해 생성자를 작성하였고 +1 씩 추가하는 메소드 GetnUpdateCounter() 함수를 호출했습니다.
Transient 은 항상 인스턴스를 생성하므로 0 값만 들어가 있을 것이며, Scoped 는 처음 컨트롤러 REQUEST 받았으므로 0 값이 할당되어 있습니다. Singleton 은 동일한 인스턴스를 재사용하므로 매번 REQUEST 할 때마다 +1씩 증가되어 결과값을 보여줍니다.
using Core1.Models;
using Microsoft.AspNetCore.Mvc;
namespace Core1.Controllers
{
public class HomeController : Controller
{
private readonly IRepository _myRepository;
public HomeController(IRepository myRepository)
{
_myRepository = myRepository;
}
public IActionResult Index()
{
ViewBag.Counter = _myRepository.GetnUpdateCounter();
return View();
}
}
}
태그를 사용하기 위해 _ViewImports.cshtml 에 기재 합니다. 네임스페이스 제일 앞 부분만 기재합니다. (Core1.TagHelpers 에서 Core1 만...)
AddScoped 생명주기는 처음 컨트롤러에서 호출하여 인스턴스를 생성 해서 우선 viewbag 에는 0 값이 할당되었고, view 에서 aspdotnet 의 taghelper 에서 인스턴스를 재사용하여 +1 되었습니다. 심재운 이라는 taghelper 를 호출해서 다시 재활용하여 +1 되어 2가 되었습니다. 다시 페이지를 새로고침하면 인스턴스를 다시 재생성하므로 아래와 동일한 결과가 나옵니다.
AddTransient 인 생명주기를 사용해 볼게요. 호출할때 마다 매번 인스턴스를 생성하니 초기값인 0이 출력되죠.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IRepository, MyRepository>();
services.AddMvc();
}
AddSingleton 은 인스턴스르 하나로 지속적으로 재활용하므로 누적되는 것을 보실 수 있습니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IRepository, MyRepository>();
services.AddMvc();
}
해당 페이지 한번 호출했을때,
해당 페이지 두번 호출했을때...
계속 누적되죠??? 하나의 인스턴스를 계속 재활용하므로 누적된다는 점만 알아두시면 됩니다.