본문 바로가기

IT 살이/04. 기술 - 프로그래밍

개발 프레임워크 만들기 대장정 09- Config를 사용한 등록작업

지난 포스트에서 말한 것처럼 이번에는 타입을 시작 프로그램에서 프로그램적으로 컨테이너에 등록했던 작업을 이제 Config로 분리해내는 작업을 하겠다. Unity 컨테이너의 완전한 Config 스키마는 새로운 것이 나올때마다 하나씩 알아보는 것으로 하겠다. 왜냐고? 지금은 필자도 다 모른다는 것이 가장 큰 이유이고 그리고 모든 것을 지금 설명하는 것은 시기상조일것이라는 생각이다. 

지난 포스트의 예제의 시작 프로그램의 코드를 다시 한번 더 보자.

namespace FSLoggerConsole

{

    class Program

    {

        static void Main(string[] args)

        {


            // 편의상 이전 로그 파일이 존재하면 삭제한다. 로그가 누적되면 테스트가 방해되잖아.

            if (System.IO.File.Exists(@"C:\FSLogger.log"))

                System.IO.File.Delete(@"C:\FSLogger.log");


            // 컨테이너 생성

            UnityContainer container = new UnityContainer();


            //DalbongAppContext에 현재 컨테이너 참조 저장

            DalbongAppContext.Current.Container = container;



            //ILogger와 FSLogger의 매핑 정보를 등록한다.

            container.RegisterType<ILogger, FSLogger>(new ContainerControlledLifetimeManager());


            SiteUserInfo userinfo = new SiteUserInfo("dalbong2");

            container.RegisterInstance<UserInfo>(userinfo, new ContainerControlledLifetimeManager());


            //Biz01 객체를 생성한다.

            Biz01 biz1 = container.Resolve<Biz01>();

            //Biz01 biz2 = container.Resolve<Biz01>();



            biz1.Save();

            //biz2.Save();


            //로그 파일의 내용을 콘솔에 출력한다.

            Console.WriteLine(System.IO.File.ReadAllText(@"C:\FSLogger.log"));

            Console.Read();


        }

    }

}

좀 수고해서 애드인을 하나 설치했더니 코드가 예쁘게 나오는군. 좋아 좋아.

앞의 코드를 보면 ILogger<->FSLogger 매핑 정보를 등록하는 부분이 있다. 이 부분을 config로 분리하겠다. 

\par ?? <\cf3 typeAlias\cf1 \cf4 alias\cf1 =\cf0 "\cf1 singleton\cf0 "\par ??\cf1 \cf4 type\cf1 =\cf0 "\cf1 Microsoft.Practices.Unity.ContainerControlledLifetimeManager,\par ?? Microsoft.Practices.Unity\cf0 "\cf1 />\par ??\par ?? \par ?? <\cf3 containers\cf1 >\par ?? <\cf3 container\cf1 \cf4 name\cf1 =\cf0 "\cf1 container01\cf0 "\cf1 >\par ?? <\cf3 types\cf1 >\par ?? \par ?? <\cf3 type\cf1 \cf4 type\cf1 =\cf0 "\cf1 Dalbong.Framework.UserInfo,Dalbong.Framework\cf0 "\cf1 \cf4 mapTo\cf1 =\cf0 "\cf1 Site.Framework.SiteUserInfo,Site.Framework\cf0 "\cf1 >\par ?? <\cf3 lifetime\cf1 \cf4 type\cf1 =\cf0 "\cf1 singleton\cf0 "\cf1 />\par ?? \par ?? <\cf3 type\cf1 \cf4 type\cf1 =\cf0 "\cf1 Dalbong.Framework.ILogger,Dalbong.Framework\cf0 "\cf1 \cf4 mapTo\cf1 =\cf0 "\cf1 Site.Framework.FSLogger,Site.Framework\cf0 "\cf1 >\par ?? <\cf3 lifetime\cf1 \cf4 type\cf1 =\cf0 "\cf1 singleton\cf0 "\cf1 />\par ?? \par ?? \par ??\par ?? \par ?? \par ?? \par ??} -->

<configuration>

  <configSections>

    <section name="unity"

          type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,

                Microsoft.Practices.Unity.Configuration, Version=1.1.0.0,

                Culture=neutral, PublicKeyToken=31bf3856ad364e35" />


  </configSections>

  <unity>

    <typeAliases>

      <!-- LifetimeMager 타입 -->

      <typeAlias alias="singleton"

          type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,

            Microsoft.Practices.Unity" />


    </typeAliases>

    <containers>

      <container name="container01">

        <types>

          <!-- 타입 매핑 등록-->

          <type type="Dalbong.Framework.ILogger,Dalbong.Framework" mapTo="Site.Framework.FSLogger,Site.Framework">

            <lifetime type="singleton" />

          </type>

        </types>


      </container>

    </containers>

  </unity>

</configuration>

<configSections> 부분에는 "unity"라는 섹션을 해석할 수 있는 핸들러를 설정하고 있다. UnityConfigurationSection 이라는 녀석이 "unity"라는 섹션을 해석할 수 있다는 것이다. 이대로 추가해주면 된다.

아래에 <unity>라는 섹션이 있고 그 안에  <typeAliases> 부분과 <containers> 요소가 있다. 두 요소 이름을 보면 복수형"~s"로 끝나는 것을 보면 각각 <typeAlias>와 <container>가 여러개 포함될 수 있을 것이라는 것을 눈치챌 수 있다. <typeAlias>는 타입에 별칭을 매핑시키는 곳이다. 앞의 예제에서 "Microsoft.Practices.Unity.ContainerControlledLifetimeManager"가 쓰일 수 있는 곳에 "singleton"이 사용될 수 있다는 것이다. <container>요소 내부에는 <types>가 있고 역시 복수형 "~s"로 끝나는 것을 봐서는 여러개의 <type>이 포함될 수 있다는 것을 알 수 있다. 예제에서는 ILogger 타입을 실제(concrete) 타입 FSLogger로 매핑한다는 것을 보여주고 있다. 그리고 그 객체는 singleton 객체라는 것을 표시해주고 있다.

간단하지만 타입 매핑 등록 설정은 끝났다. 이제 이 설정을 코드상에서 컨테이너에 로딩하는 작업이 필요하다. 코드는 다음과 같다.

namespace FSLoggerConsole

{

    class Program

    {

        static void Main(string[] args)

        {



            // 컨테이너 생성

            IUnityContainer container = new UnityContainer();


  • //설정 내용을 컨테이너로 로딩한다.
  • UnityConfigurationSection section
  • = (UnityConfigurationSection)onfigurationManager.GetSection("unity");
  • section.Containers["container01"].Configure(container);

            //DalbongAppContext에 현재 컨테이너 참조 저장

            DalbongAppContext.Current.Container = container;


  • //ILogger와 FSLogger의 매핑 정보를 등록한다.
  • //container.RegisterType<ILogger, FSLogger>(new ContainerControlledLifetimeManager());

            SiteUserInfo userinfo = new SiteUserInfo("dalbong2");

            container.RegisterInstance<UserInfo>(userinfo, new ContainerControlledLifetimeManager());


            ...

           

        }

    }

}

이제 실행을 하면 이전 결과와 동일한 효과가 있다. 그러나 그전에 다음 두개의 어셈블리에 대한 참조를 추가해야 한다.

Unity 컨테이너를 사용한 간단한 예제를 마친다. 다음 포스트부터는 Unity 블럭을 제작하는 데 사용한 Dependency Injection 패턴을  알아볼 것이고 Unity 블럭에서 그 패턴을 어떻게 적용되고 있는지 알아보겠다.  근데, Dependency Injection 패턴도 일반 다른 패턴들처럼 설명하고 정리하기가 필자에게는 상당히 힘든 일이다. 이 블로그에는 분명 패턴과 관련된 카테고리가 있음에도 아직 관련 포스트를 제대로 올리지 못한 것은 관심은 있으나 아직 정리할 실력이 되지 못한다는 것이다. 이 부분을 정리하는데 상당한 시간이 소요될 것 같다. 그리고 Unity 컨테이너를 확장하는 방법에 대해서도 알아보면서 Unity 컨테이너를 좀 더 상세히 알아보겠다.