본문으로 바로가기

c#Typeof로 동적 인스턴스 만들기

category 개발언어/C# 2017. 5. 19. 17:38

MFC에서는 RuntimeClass라는 것이 있어서, 클래스를 별도로 관리할 수 있다.
즉 new 연산자를 사용하여 객체를 메모리에 바로 할당하지 않고 클래스의 속성만 보관하고 있다가.
필요한 경우 RuntimeClass를 호출하여 객체를 생성할 수 있다.

복잡하고 다양한 조건의 경우를 수용하는 프로그램을 개발하고자 하는 경우 조건문만으로 프로그램의 동작을 구성하는 것은 한계가 있다.
관리도 어렵고,코드가 길이져서 매우 혼란스런 산출물을 만들 가능성이 높다.

나의 경우는 이런 문제를 방지하고자 중복 충돌을 방지 하기 위해 런타임 클래스를 사용하여 조건에 따라 대표되는 클래스를 호출하고, 
각각의 조건에 해당하는 대표클래스를 상속하여 조건에 적합한 클래스를 구현 하는 방법을 선호한다.

이렇게 하면 코드가 복잡해져도 
클래스가 분리 되어있으므로 검증된 클래스에 대해서는 재차 검증할 필요가 없다.
간혹의 경우 내부에서 두가지 버젼을 만들어 두었다가 상황에 따라서 해당 버젼을 적용하여 안전하게 적용할 수도 있다.

그런데 C#에서 이런 문제를 어떻게 해결 할 까?

1. 객체를 직접생성해고 선택적으로 호출하는 방법
   이 방법은 이글의 주제과 관계없이 초보적인 단계, 혹은 RuntimeClass에 대한 개념이 없을때 사용하는 비정상적인 기법이다.
   아래의 예제는 콜렉션을 맏들어서 Form 개체를 할당하고, MessageBox로 조건을 선택하고, 해당조건에 해당하는 Form클래스를 실행할 수 있도록 되어 있다.
이렇게 하면 복작한 if, Switch 문을 사용하지 않고 콜렉션에 추가된 클래스만 등록하면 되는 이저미 있지만 클래스 갯수가 늘어난면 메모리 낭비가 심할 수 밖에 없다, 소스코드에서는 여려개의 클래스가 나열되어 있지만, 실제 동작에서는 특정조건에 적합한 오직 하나의 클래스만 선택되어 메모리에 생성되면 되는데에도 불구 하고 많은 불필요한 메모리 낭비가 이루어 진다.

static Dictionary<string, object> mDic;//콜렉션을 만들고 object mOb; mDic = new Dictionary<string, object>();

mDic.Add("SDI", new FormList()); mDic.Add("MDI", new MDIParent()); DialogResult result = MessageBox.Show("SDI를 실행하시겠습니까?", "동작선택", MessageBoxButtons.YesNo); if (result == DialogResult.Yes) mDic.TryGetValue("SDI", out mOb); else mDic.TryGetValue("MDI", out mOb); Application.Run((Form) mOb)

2. Typeof를 사용하여 클래스의 자료형만 등록하고 필요시 선택된 하나의 클래스만 메모리에 로드 되도록 작성된 코드 예제
   C# 에서 Typeof를 사용하여 MFC의 Runtimeclass의 기능을 구현 할 수 있다.
   여기서 주목 할 것은 
Activator.CreateInstance(t, null);   사용하여 인스턴스를 생성하는 부분이다

 #region |TestSample Class|
    class Human
    {
        public void Walk(String place)
        {
            Console.WriteLine("Human walking to " + place);
        }
    }
    class Animal
    {
        public void Walk(String place)
        {
            Console.WriteLine("Animal walking from " + place);
        }
    }
    #endregion 
    static class Program
    {
        static Dictionary mTDic;
   
        /// 
        [STAThread]
        static void Main()
        {           
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
   
            #region |런타임클래스 사용(Typeof로 자료형에서 직접 인스턴스생성)예|         
            Type t;
            mTDic = new Dictionary()<string, Type>();
            
            //case 1 클래스의 Method를 호출하는 예
             mTDic.Add("Human", typeof(Human));
         mTDic.Add("Animal", typeof(Animal));
             
            mTDic.TryGetValue("Human", out t);
            var obj1 = Activator.CreateInstance(t, null);
            t.InvokeMember("Walk", BindingFlags.InvokeMethod, null, obj1, new object[] { "london" });

            mTDic.TryGetValue("Animal", out t);
            dynamic formobj = Activator.CreateInstance(t, null);
            formobj.Walk( "london" );
        #endregion
        }
    }
}


#런타임클래스,#동적호출,#클래스의 동적생성,#특정조건에맞는 클래스 자동 선택