■ 동적 클래스 사용하기 예제

----------------------------------------------------------------------------------------------------

using System;

 

DynamicClass dynamicClass = new DynamicClass();

 

dynamicClass.AddProperty("ID"  , typeof(string));

dynamicClass.AddProperty("Name", typeof(string));

 

dynamicClass.CreateType();

 

dynamicClass.CreateInstance();

 

dynamicClass.SetValue(0, "0001"  );

dynamicClass.SetValue(1, "홍길동");

 

dynamic employee = dynamicClass.Instance;

 

Console.WriteLine(employee.ID  );

Console.WriteLine(employee.Name);

----------------------------------------------------------------------------------------------------

 

■ 동적 클래스 사용하기

----------------------------------------------------------------------------------------------------

using System;

using System.Collections.Generic;

using System.Reflection;

using System.Reflection.Emit;

 

/// <summary>

/// 동적 클래스

/// </summary>

public class DynamicClass : IDisposable

{

    //////////////////////////////////////////////////////////////////////////////////////////////////// Field

    ////////////////////////////////////////////////////////////////////////////////////////// Static

    //////////////////////////////////////////////////////////////////////////////// Private

 

    #region Field

 

    /// <summary>

    /// 모듈 빌더

    /// </summary>

    private static ModuleBuilder _moduleBuilder;

 

    /// <summary>

    /// 클래스 카운트

    /// </summary>

    private static int _classCount;

 

    #endregion

 

    ////////////////////////////////////////////////////////////////////////////////////////// Instance

    //////////////////////////////////////////////////////////////////////////////// Private

 

    #region Field

 

    /// <summary>

    /// 타입 빌더

    /// </summary>

    private TypeBuilder typeBuilder;

 

    /// <summary>

    /// 멤버 정보 리스트

    /// </summary>

    private List<MemberInfo> memberInfoList = new List<MemberInfo>();

 

    /// <summary>

    /// 타입

    /// </summary>

    private Type type;

 

    /// <summary>

    /// 인스턴스

    /// </summary>

    private object instance;

 

    /// <summary>

    /// GET 함수 리스트

    /// </summary>

    private List<Func<object, object>> getFunctionList = new List<Func<object, object>>();

 

    /// <summary>

    /// SET 액션 리스트

    /// </summary>

    private List<Action<object, object>> setActionList = new List<Action<object, object>>();

 

    #endregion

 

    //////////////////////////////////////////////////////////////////////////////////////////////////// Property

    ////////////////////////////////////////////////////////////////////////////////////////// Public

 

    #region 인스턴스 - Instance

 

    /// <summary>

    /// 인스턴스

    /// </summary>

    public object Instance

    {

        get

        {

            return this.instance;

        }

    }

 

    #endregion

 

    //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

    ////////////////////////////////////////////////////////////////////////////////////////// Public

 

    #region 생성자 - DynamicClass

 

    /// <summary>

    /// 생성자

    /// </summary>

    public DynamicClass()

    {

        if(_moduleBuilder == null)

        {

            AssemblyName assemblyName = new AssemblyName("DynamicAssembly");

 

            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

 

            _moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");

        }

 

        this.typeBuilder = _moduleBuilder.DefineType("DynamicClass_" + _classCount.ToString(), TypeAttributes.Public);

 

        _classCount++;

    }

 

    #endregion

 

    //////////////////////////////////////////////////////////////////////////////////////////////////// Method

    ////////////////////////////////////////////////////////////////////////////////////////// Public

 

    #region 필드 추가하기 - AddField(fieldName, fieldType)

 

    /// <summary>

    /// 필드 추가하기

    /// </summary>

    /// <param name="fieldName">필드명</param>

    /// <param name="fieldType">필드 타입</param>

    public void AddField(string fieldName, Type fieldType)

    {

        FieldBuilder fieldBuilder = this.typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Public);

 

        this.memberInfoList.Add(fieldBuilder);

    }

 

    #endregion

 

    #region 속성 추가하기 - AddProperty(propertyName, propertyType)

 

    /// <summary>

    /// 속성 추가하기

    /// </summary>

    /// <param name="propertyName">속성명</param>

    /// <param name="propertyType">속성 타입</param>

    public void AddProperty(string propertyName, Type propertyType)

    {

        FieldBuilder fieldBuilder = this.typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

 

        PropertyBuilder propertyBuilder = this.typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);

 

        MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

 

        MethodBuilder getMethodBuilder = this.typeBuilder.DefineMethod("get_" + propertyName, methodAttributes, propertyType, Type.EmptyTypes);

 

        ILGenerator getILGenerator = getMethodBuilder.GetILGenerator();

 

        getILGenerator.Emit(OpCodes.Ldarg_0);

        getILGenerator.Emit(OpCodes.Ldfld, fieldBuilder);

        getILGenerator.Emit(OpCodes.Ret);

 

        propertyBuilder.SetGetMethod(getMethodBuilder);

 

        MethodBuilder setMethodBuilder = this.typeBuilder.DefineMethod("set_" + propertyName, methodAttributes, null,

            new Type[] { propertyType });

 

        ILGenerator setILGenerator = setMethodBuilder.GetILGenerator();

 

        setILGenerator.Emit(OpCodes.Ldarg_0);

        setILGenerator.Emit(OpCodes.Ldarg_1);

        setILGenerator.Emit(OpCodes.Stfld, fieldBuilder);

        setILGenerator.Emit(OpCodes.Ret);

 

        propertyBuilder.SetSetMethod(setMethodBuilder);

 

        this.memberInfoList.Add(propertyBuilder);

    }

 

    #endregion

 

    #region 타입 생성하기 - CreateType()

 

    /// <summary>

    /// 타입 생성하기

    /// </summary>

    public void CreateType()

    {

        this.type = this.typeBuilder.CreateType();

 

        foreach(MemberInfo info in this.memberInfoList)

        {

            switch(info.MemberType)

            {

                case MemberTypes.Field :

 

                    FieldInfo fieldInfo = this.type.GetField(info.Name);

 

                    this.setActionList.Add(fieldInfo.SetValue);

 

                    this.getFunctionList.Add(fieldInfo.GetValue);

 

                    break;

 

                case MemberTypes.Property :

 

                    PropertyInfo propertyInfo = this.type.GetProperty(info.Name);

 

                    this.setActionList.Add(propertyInfo.SetValue);

 

                    this.getFunctionList.Add(propertyInfo.GetValue);

 

                    break;

            }

        }

    }

 

    #endregion

 

    #region 인스턴스 생성하기 - CreateInstance()

 

    /// <summary>

    /// 인스턴스 생성하기

    /// </summary>

    /// <returns>인스턴스</returns>

    public object CreateInstance()

    {

        this.instance = Activator.CreateInstance(this.type);

 

        return this.instance;

    }

 

    #endregion

 

    #region 값 설정하기 - SetValue(index, value)

 

    /// <summary>

    /// 값 설정하기

    /// </summary>

    /// <param name="index">인덱스</param>

    /// <param name="value"></param>

    public void SetValue(int index, object value)

    {

        this.setActionList[index](this.instance, value);

    }

 

    #endregion

 

    #region 값 구하기 - GetValue(index)

 

    /// <summary>

    /// 값 구하기

    /// </summary>

    /// <param name="index">인덱스</param>

    /// <returns></returns>

    public object GetValue(int index)

    {

        return this.getFunctionList[index](this.instance);

    }

 

    #endregion

 

    #region 리소스 해제하기 - Dispose()

 

    /// <summary>

    /// 리소스 해제하기

    /// </summary>

    public void Dispose()

    {

        this.instance = null;

 

        this.type = null;

 

        this.typeBuilder = null;

 

        this.setActionList.Clear();

 

        this.getFunctionList.Clear();

 

        this.memberInfoList.Clear();

    }

 

    #endregion

}

----------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요