첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

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

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);

 

728x90

 

▶ 동적 클래스 사용하기

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
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요