Section 44.1: C# 과 ASP.NET 에서 Unity 를 통한 Dependency Injection 사용하기

우선적으로, 사용자의 코드에서 Dependency Injection 을 사용하여야 할 이유는 무엇일까? 이는 사용자의 프로그램 내 특정 구성 요소 (component) 들을 다른 클래스들로부터 분리 (decouple) 하기 위함이다. 다음과 같은 AnimalController 클래스가 있다고 가정을 해보자:

public class AnimalController() { private SantaAndHisReindeer _SantaAndHisReindeer = new SantaAndHisReindeer(); public AnimalController() { Console.WriteLine(""); } }

해당 코드 자체만 보면 아무런 문제가 없다고 생각할 수도 있겠지만, 이러한 경우 AnimalController_SantaAndHisReindeer 객체 자체에 의존성을 갖게 된다. 이로 인해 우리의 Controller 는 테스트하기 어려운 구조를 갖게 되며, 코드의 재사용성 역시 나빠지는 결과를 초래하게 된다.

Depedency Injection 과 인터페이스를 사용해야 하는 이유에 대해서는 이곳 에 설명이 상세히 되어 있다.

만약 Unity 가 DI (Dependency Injection) 를 처리하게 하고자 한다면, 해당 과정은 매우 간단하다. NuGet (패키지 관리자) 을 이용하여 손쉽게 기존 코드에 Unity 를 import 할 수 있다.

Visual Studio Tools -> NuGet Package Manager -> Manage Packages for Solution -> 검색창에서 Unity 입력 -> 프로젝트 선택 -> 설치

이제 주석이 잘 달려있는 두개의 파일이 생성될 것이다 : App-Data 폴더 내의 UnityConfig.csUnityMvcActivator.cs

UnityConfigRegisterTypes 메소드에서는, 사용자의 생성자에서 주입될 타입들을 확인할 수 있다.

namespace Vegan.WebUi.App_Start { public class UnityConfig { #region Unity Container private static Lazy < IUnityContainer > container = new Lazy < IUnityContainer > (() => { var container = new UnityContainer(); RegisterTypes(container); return container; }); /// <summary> /// Gets the configured Unity container. /// </summary> public static IUnityContainer GetConfiguredContainer() { return container.Value; } #endregion /// <summary>Registers the type mappings with the Unity container.</summary> /// <param name="container">The unity container to configure.</param> /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered. < /remarks> public static void RegisterTypes(IUnityContainer container) { // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements. // container.LoadConfiguration(); // TODO: Register your types here // container.RegisterType<IProductRepository, ProductRepository>(); container.RegisterType < ISanta, SantaAndHisReindeer > (); } } }

UnityMvcActivator -> 마찬가지로 해당 클래스가 Unity 를 ASP.NET MVC 와 연동시켜 줄 것이라는 상세한 주석을 확인할 수 있다.

using System.Linq; using System.Web.Mvc; using Microsoft.Practices.Unity.Mvc; [assembly: WebActivatorEx.PreApplicationStartMethod(typeof (Vegan.WebUi.App_Start.UnityWebActivator), "Start") ] [assembly: WebActivatorEx.ApplicationShutdownMethod(typeof (Vegan.WebUi.App_Start.UnityWebActivator), "Shutdown") ] namespace Vegan.WebUi.App_Start { /// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary> public static class UnityWebActivator { /// <summary>Integrates Unity when the application starts.</summary> public static void Start() { var container = UnityConfig.GetConfiguredContainer(); FilterProviders.Providers.Remove(FilterProviders.Providers.OfType < FilterAttributeFilterProvider > ().First()); FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container)); DependencyResolver.SetResolver(new UnityDependencyResolver(container)); // TODO: Uncomment if you want to use PerRequestLifetimeManager // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof (UnityPerRequestHttpModule)); } /// <summary>Disposes the Unity container when the application is shut down.</summary> public static void Shutdown() { var container = UnityConfig.GetConfiguredContainer(); container.Dispose(); } } }

이제 우리는 Controller 를 SantAndHisReindeer 클래스로부터 분리할 수 있다.

public class AnimalController() { private readonly SantaAndHisReindeer _SantaAndHisReindeer; public AnimalController(SantaAndHisReindeer SantaAndHisReindeer) { _SantAndHisReindeer = SantaAndHisReindeer; } }

이제 최종적으로 어플리케이션을 실행하기 전 수행해주어야 하는 마지막 작업이 남아있다.

Global.asax.cs 에서 다음과 같은 코드를 추가해 주어야 한다:

UnityWebActivator.Start()

이는 Unity 를 시작 및 구성하며 사용자의 타입들을 등록해 줄 것이다.

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; using Vegan.WebUi.App_Start; namespace Vegan.WebUi { public class MvcApplication: System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); UnityWebActivator.Start(); } } }
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

+ Recent posts