[실습으로 다지는 C#] 런타임에 라이브러리 로딩하여 사용하기 – .NET 리플렉션

안녕하세요. 언제나 휴일에 언휴예요.

1. 런타임에 라이브러리 로딩? 리플렉션!

 

이번 실습은 프로그램이 동작하는 런타임에 라이브러리를 로딩하여 사용하는 것을 해 볼 거예요.

.NET에서는 리플렉션이라는 기술을 제공하고 있으며 이를 이용하여 런타임에 라이브러리를 로딩하여 사용합니다.

런타임에 라이브러리를 로딩하여 사용한다는 것은 무슨 의미일까요?

예를 들어 미디어 플레이어 응용과 코덱 라이브러리는 배포자가 다를 수 있습니다.

미디어 플레이어 응용에서 미디어를 선택하여 재생 버튼을 누르면 미디어의 압축 형태에 맞는 코덱 라이브러리를 로딩하여 재생합니다.

만약 코덱 라이브러리가 없으면 코덱이 없다고 메시지 창을 띄워줍니다.

이처럼 동작하려면 미디어 플레이어 응용은 코덱을 참조하여 구현하는 것이 아니라 명시적으로 로딩하여 사용하게 구현해야 합니다.

만약 참조하여 구현하면 응용이 시작할 때 해당 라이브러리가 없으면 예외를 발생하여 프로그램은 종료합니다.

테스트 할 라이브러리를 만들고 참조 추가하지 마세요.

만든 라이브러리 파일을 명시적 어셈블리 로딩할 프로그램 실행 파일이 있는 곳으로 복사하세요.

2. 라이브러리 소스 코드

using System;

namespace DemoLib
{
    public class Demo
    {
        int num;
        public int Num
        {
            get
            {
                return num;
            }
        }
        public int Add(int a,int b)
        {
            Console.WriteLine("Add 메서드 호출 됨:{0},{1}", a, b);
            return a + b;
        }
        public Demo(int n)
        {
            Console.WriteLine("Demo 생성자 호출됨:{0}", n);
            num = n;
        }
        public static void Foo(string msg)
        {
            Console.WriteLine("Foo 메서드 호출됨:{0}", msg);
        }
    }
}

3. 명시적으로 라이브러리 로딩 예제

/* https://ehpub.co.kr
 * Reflection
 * 명시적 어셈블리 로딩                                                                                             
 */

using System;
using System.Reflection;

namespace 닷넷_리플렉션___명시적_어셈블리_로딩하여_사용하기
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Assembly asm = Assembly.Load("DemoLib");
                //Type[] types = asm.GetTypes();
                //foreach(Type type in types)
                //{
                //    Console.WriteLine(type);
                //}
                Type type = asm.GetType("DemoLib.Demo");
                object[] objs = new object[] { 5 };
                object demo_ins = Activator.CreateInstance(type,objs);

                PropertyInfo pi = type.GetProperty("Num");
                int num = (int)pi.GetValue(demo_ins);
                Console.WriteLine("번호:{0}", num);

                MethodInfo mi = type.GetMethod("Add");
                objs = new object[] { 3, 7 };
                int re = (int)mi.Invoke(demo_ins, objs);
                Console.WriteLine("반환:{0}", re);

                mi = type.GetMethod("Foo");
                objs = new object[] { "헬로우" };
                mi.Invoke(null, objs);
                
                Console.WriteLine("테스트 종료");
            }
            catch(Exception ex)
            {
                Console.WriteLine("예외 발생");
            }
        }
    }
}