개요

ASP.NET WebForm 에서 Dependency Injection 을 사용하는 방법을 소개한다. IoC Container 를 이용하여 System.Web.UI.Page 를 상속하는 페이지에서 Injection 을 해야 하는데, 이를 위해 IHttpHandlerFactory 를 사용하는 방법을 소개한다.

여기에서는 필자가 꾸준히 만들어 온 Unity ContainerWindsor Castle 을 기반으로 하는 Umc.Core 프레임워크를 사용한다.Umc.Core 프레임워크에는 Unity Auto Registration 기능등이 모두 포함하기 때문에 프로젝트 셋업에 편리하다는 장점도 있다.

샘플 프로젝트는 필자의 github 에서 다운로드 받을 수 있다.
https://github.com/powerumc/WebForm-DependencyInjection 

프로젝트 셋업

먼저 프로젝트를 만들고, nuget 을 이용하여 umc.core 프레임워크를 설치한다.

nuget install umc.core

그리고, Umc.Core 에 구현에 놓은 IHttpHandlerFactory 를 샘플 프로젝트에 추가해 놓았다. 이를 web.config 에 추가해 주면 된다.

<system.webServer>
    <handlers>
      <add name="WebFormPageHandlerFactory" verb="*" path="*.aspx"  type="WebForm_DependencyInjection.FrameworkContainerPageHandlerFactory"/>
    </handlers>
</system.webServer>

FrameworkContainerPageHandlerFactory 클래스의 구현은 아래의 코드를 참고하면 된다. 다만, 아래 구현 코드에서 BuildManager.CreateInstanceFromVirtualPath 를 대신 사용하면 절대 안된다.

public class FrameworkContainerPageHandlerFactory : IHttpHandlerFactory
{
    public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
        var handler = BuildManager.GetObjectFactory(url, false).CreateInstance();
        if (handler.GetType().ToString().StartsWith("ASP."))
        {
            var container = context.Application["container"] as IFrameworkContainer;
            return container.Resolve(handler.GetType().BaseType) as IHttpHandler;
        }

        return handler as IHttpHandler;
    }

    public void ReleaseHandler(IHttpHandler handler)
    {
    }
}

웹 응용프로그램 Bootstrap

그 다음 할 일은 어떤 컴포넌트들을 IoC 에 등록하고 이를 Composition 할 지 코드를 통해 구현한다. ASP.NET WebForm 에서는 Global.asax.cs 의 Application_Start 메서드에 구현하는 게 가장 적절하다.

그러나 이는 RELEASE 용 빌드인 경우가 그렇고, 개발 중인 경우, 즉 DEBUG 모드 빌드인 경우 Session_Start 에 구현해 놓는 것도 좋을 것 같다.

public class Global : System.Web.HttpApplication
{
  private static IFrameworkContainer container;

  protected void Application_Start(object sender, EventArgs e)
  {
      container = new FrameworkContainerForUnity();

      var catalog = new FrameworkAssemblyCatalog(Assembly.GetExecutingAssembly());
      var visitor = new FrameworkDependencyVisitor(catalog);
      var resolver = new FrameworkCompositionResolverForUnity((FrameworkContainerForUnity)container, visitor.VisitTypes());
      resolver.Compose();

      Application.Lock();
      Application["container"] = container;
      Application.UnLock();
    }
  }

FrameworkAssemblyCatalogFrameworkCatalog를 구현한 클래스로 컴포넌트를 등록하는 방법을 구현하는 클래스다.

FrameworkDependencyVisitor 는 catalog 에서 검색된 컴포넌트들을 구석 구석 방문해서 Comsoition 을 위해 객체 그래프를 그리는 클래스다.

FrameworkCompositionResolverForUnity 는 객체 그래프를 IoC Container 에 등록하는 클래스다.

이렇게 몇 줄의 코드로 Auto Registration 과정이 모두 끝난다.

서비스 구현

간단하게 Dependency Inection 을 테스트하기 위해서 IEmailService 인터페이스와 이를 구현한 코드다.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using Umc.Core;

namespace WebForm_DependencyInjection.Services
{
    public interface IEmailService
    {
        bool Send(string to, string contents);
    }

    [DependencyContract(typeof(IEmailService))]
    public class EmailService : IEmailService
    {
        public bool Send(string to, string contents)
        {
            HttpContext.Current.Response.Write("Send email.");
            return true;
        }
    }
}

페이지 구현

이제 모두 다 됐다. Dependency Injection 이 필요한 프로퍼티에 [DependencyInjection] 특성을 선언하면 Index 페이지 인스턴스가 생성될 때 컨테이너에 등록된 컴포넌트가 주입된다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Umc.Core;
using WebForm_DependencyInjection.Services;

namespace WebForm_DependencyInjection
{
    public partial class Index : System.Web.UI.Page
    {
        // Here.. Injection for IEmailService.
        [DependencyInjection]
        protected IEmailService EmailService { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            EmailService.Send("", "");
        }
    }
}


저작자 표시 비영리 동일 조건 변경 허락
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 땡초 POWERUMC

댓글을 달아 주세요