[C#] ASP.NET의 MVC Framework에서 DI 의존성 주입을 하는 방법


Development note/C#  2019. 11. 28. 09:00

안녕하세요. 명월입니다.


이 글은 C#의 ASP.NET의 MVC Framework에서 DI 의존성 주입을 하는 방법에 대한 설명입니다.


의존성 주입(Dependency Injection)이라는 것은 프로젝트 내에서 클래스를 자주 사용함에 있어 여러번 생성을 하지 않고 한번의 생성으로 재사용을 하면서 싱글톤의 단점인 상속이 불가능한 것을 보안하고 클래스 내의 객체에 인스턴스를 주입하는 것을 말합니다. 즉, 외부 객체에서 Controller가 호출될 때 내부 객체의 클래스에 값을 주입 시켜주는 것을 뜻합니다.


예전에 코딩으로 설명한 적이 있습니다.

링크 - [Design pattern - 실무편] 의존성 주입 (Dependency Injection) 구현하기


자바에서는 mvc-config 파일에서 설정하여 클래스를 주입합니다.

링크 - [Java강좌 - 53] JPA의 Spring framework에서 DI(의존성 주입)를 이용해 매핑하는 방법(@Autowired 사용 방법)


MVC Framework를 생성하는 것은 아래의 링크를 참조해 주세요.

링크 - https://nowonbun.tistory.com/503 [C# 강좌 - 67] MVC Framework 프로젝트 생성하기


그럼 MVC Framework를 하나 생성하겠습니다.

그리고 MVC에서는 의존성 주입을 위해서는 별도의 라이브러리가 필요한데 Nuget으로 다운 받겠습니다.

그리고 검색 창에 Unity.MVC라고 검색을 하면 여러가지가 뜨는 데 우리는 Unity.Mvc4를 다운 받습니다.

그럼 의존성 주입할 파일의 인터페이스와 클래스를 만듭니다.


저의 경우는 Service 폴더에 Interface 폴더 안에는 Interface를 Service 폴더 안에는 실행 클래스를 생성하겠습니다.

namespace DependencyInjectionExample.Service.Interface
{
  public interface ITestService
  {
    int GetCounting();
  }
}
using DependencyInjectionExample.Service.Interface;

namespace DependencyInjectionExample.Service
{
  public class TestService : ITestService
  {
    private int val = 0;
    // 호출 될때 마다 카운딩을 한다.
    public int GetCounting()
    {
      this.val++;
      return this.val;
    }
  }
}

그리고 프로젝트를 보면 Bootstrapper.cs 파일이 있습니다.

BuildUnityContainer 함수에 추가할 의존성 주입 클래스를 정의합니다.

using System.Web.Mvc;
using Microsoft.Practices.Unity;
using Unity.Mvc4;
using DependencyInjectionExample.Service;
using DependencyInjectionExample.Service.Interface;

namespace DependencyInjectionExample
{
  public static class Bootstrapper
  {
    public static IUnityContainer Initialise()
    {
      var container = BuildUnityContainer();

      DependencyResolver.SetResolver(new UnityDependencyResolver(container));

      return container;
    }

    private static IUnityContainer BuildUnityContainer()
    {
      var container = new UnityContainer();
      // 의존성 주입은 Generation 타입에 앞은 Interface 뒤는 Class 타입을 넣습니다.
      container.RegisterType<ITestService, TestService>(new ContainerControlledLifetimeManager());

      RegisterTypes(container);

      return container;
    }

    public static void RegisterTypes(IUnityContainer container)
    {

    }
  }
}

container.RegisterType타입 파라미터에 아무것도 넣지 않으면 TransientLifetimeManager 타입으로 돌아가는데 이는 Controller를 호출할 때마다 Service 클래스를 재 생성하겠다는 의미입니다.

링크 - https://www.tutorialsteacher.com/ioc/lifetime-manager-in-unity-container

Lifetime Manager 설명
TransientLifetimeManager Resolve 또는 ResolveAll 메서드를 호출 할 때마다 요청 된 유형의 새 개체를 만듭니다.
ContainerControlledLifetimeManager Resolve 또는 ResolveAll 메서드를 처음 호출 할 때 싱글톤 개체를 만든 다음 후속 Resolve 또는 ResolveAll 호출에서 동일한 개체를 반환합니다.
HierarchicalLifetimeManager ContainerControlledLifetimeManager와 마찬가지로 유일한 차이점은 하위 컨테이너가 자체 단일 객체를 만들 수 있다는 것입니다. 부모 컨테이너와 자식 컨테이너는 동일한 단일 객체를 공유하지 않습니다.
PerResolveLifetimeManager TransientLifetimeManager와 유사하지만 재귀 객체 그래프에서 등록 된 유형의 동일한 객체를 재사용합니다.
PerThreadLifetimeManager 스레드 당 단일 객체를 만듭니다. 다른 스레드의 컨테이너에서 다른 객체를 반환합니다.
ExternallyControlledLifetimeManager Resolve 또는 ResolveAll 메서드를 호출 할 때 생성 한 개체에 대한 약한 참조 만 유지합니다. 강력한 개체의 수명을 유지하지 않으며 가비지 수집기에서 개체의 수명을 제어 할 수 있습니다. 사용자 정의 평생 관리자를 만들 수 있습니다.

저는 싱글톤 객체를 생성하게 만들었습니다.


그리고 Global.asax 파일에서 아래의 코드를 추가합니다.

protected void Application_Start()
{
  ...
  // 추가한다.
  Bootstrapper.Initialise();
}

여기까지 의존성 주입 설정을 완료했습니다. 이제 실제로 Controller에서 사용해 보겠습니다.

HomeController로 가서 생성자를 만들고 의존성 주입할 인터페이스를 만듭니다.

using DependencyInjectionExample.Service.Interface;

namespace DependencyInjectionExample.Controllers
{
  public class HomeController : Controller
  {
    // 생성자로 부터 의존성 주입 인스턴스가 오면 맴버 변수로 보관한다.
    private readonly ITestService _service;

    public HomeController(ITestService service)
    {
      this._service = service;
    }

    public ActionResult Index()
    {
      // /Home/Index 가 호출되면 의존성 주입된 인스턴스의 GetCounting 함수를 호출한다.
      ViewBag.Count = this._service.GetCounting();
      return View();
    }
  }
}

그리고 View파일로 가서 다른 소스는 모두 지우고 ViewBag의 값만 출력하게 끔 수정합니다.

@{
  Layout = null;
}
@ViewBag.Count

이제 실행보도록 하겠습니다.

여기까지는 ITestService가 HomeController에 의존성 주입이 되어서 값이 나옵니다.

이번에는 페이지 재요청을 여러번 해 보겠습니다.

싱글톤 값으로 값이 계속 증가하는 것을 확인할 수 있습니다.

첨부 파일 - DependencyInjectionExample.zip


참조 링크 - https://docs.microsoft.com/...

참조 링크 - https://www.tutorialsteacher.com/...


여기까지 C#의 ASP.NET의 MVC Framework에서 DI 의존성 주입을 하는 방법에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.