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

■ ITypedList 인터페이스 : TypedCollection<T> 만들기 예제

using System;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Class
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 임직원 - Employee

        /// <summary>
        /// 임직원
        /// </summary>
        private class Employee
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region Field

            /// <summary>
            /// 아이디
            /// </summary>
            public string ID;

            /// <summary>
            /// 성명
            /// </summary>
            public string Name;

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            this.gridControl.DataSource = GetCollection(); // Employee 필드도 바인딩이 정상적으로 된다.
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 컬렉션 구하기 - GetCollection()

        /// <summary>
        /// 컬렉션 구하기
        /// </summary>
        /// <returns>컬렉션</returns>
        private TypedCollection<Employee> GetCollection()
        {
            TypedCollection<Employee> collection = new TypedCollection<Employee>();

            collection.Add(new Employee(){ ID = "A", Name = "홍길동" });
            collection.Add(new Employee(){ ID = "B", Name = "강동구" });
            collection.Add(new Employee(){ ID = "C", Name = "홍길숙" });

            return collection;
        }

        #endregion
    }
}

※ this.gridControl은 그리드 컨트롤을 가정한다.

 

728x90

 

■ ITypedList 인터페이스 : TypedCollection<T> 만들기

 

▶ TypedPropertyDescriptor.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace TestProject
{
    /// <summary>
    /// 타입 속성 설명자
    /// </summary>
    /// <typeparam name="T">타입</typeparam>
    public class TypedPropertyDescriptor<T> : PropertyDescriptor
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// GetValue 함수
        /// </summary>
        private Func<object, object> getValue;

        /// <summary>
        /// SetValue 액션
        /// </summary>
        private Action<object, object> setValue;

        /// <summary>
        /// 타입
        /// </summary>
        private Type type;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 컴포넌트 타입 - ComponentType

        /// <summary>
        /// 컴포넌트 타입
        /// </summary>
        public override Type ComponentType
        {
            get
            {
                return typeof(TypedCollection<T>);
            }
        }

        #endregion

        #region 읽기 전용 여부 - IsReadOnly

        /// <summary>
        /// 읽기 전용 여부
        /// </summary>
        public override bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        #endregion

        #region 속성 타입 - PropertyType

        /// <summary>
        /// 속성 타입
        /// </summary>
        public override Type PropertyType
        {
            get
            {
                return this.type;
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - TypedPropertyDescriptor(getValue, setValue, memberName, type)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="getValue">GetValue 함수</param>
        /// <param name="setValue">SetValue 액션</param>
        /// <param name="memberName">멤버명</param>
        /// <param name="type">타입</param>
        public TypedPropertyDescriptor(Func<object, object> getValue, Action<object, object> setValue, string memberName, Type type) : base(memberName, null)
        {
            this.getValue = getValue;
            this.setValue = setValue;
            this.type     = type;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 값 리셋 가능 여부 구하기 - CanResetValue(component)

        /// <summary>
        /// 값 리셋 가능 여부 구하기
        /// </summary>
        /// <param name="component">컴포넌트</param>
        /// <returns>값 리셋 가능 여부</returns>
        public override bool CanResetValue(object component)
        {
            return false;
        }

        #endregion

        #region 값 구하기 - GetValue(component)

        /// <summary>
        /// 값 구하기
        /// </summary>
        /// <param name="component">컴포넌트</param>
        /// <returns>값</returns>
        public override object GetValue(object component)
        {
            return this.getValue(component);
        }

        #endregion

        #region 값 리셋하기 - ResetValue(component)

        /// <summary>
        /// 값 리셋하기
        /// </summary>
        /// <param name="component">컴포넌트</param>
        public override void ResetValue(object component)
        {
            this.setValue(component, null);
        }

        #endregion

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

        /// <summary>
        /// 값 설정하기
        /// </summary>
        /// <param name="component">컴포넌트</param>
        /// <param name="value">값</param>
        public override void SetValue(object component, object value)
        {
            this.setValue(component, value);
        }

        #endregion

        #region 값 직렬화 여부구하기 - ShouldSerializeValue(component)

        /// <summary>
        /// 값 직렬화 여부 구하기
        /// </summary>
        /// <param name="component">컴포넌트</param>
        /// <returns>값 직렬화 여부</returns>
        public override bool ShouldSerializeValue(object component)
        {
            return true;
        }

        #endregion
    }
}

 

300x250

 

▶ TypedCollection.cs

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Reflection;

namespace TestProject
{
    /// <summary>
    /// 타입 컬렉션
    /// </summary>
    /// <typeparam name="T">타입</typeparam>
    [Serializable]
    public class TypedCollection<T> : ObservableCollection<T>, ITypedList
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 속성 설명자 컬렉션
        /// </summary>
        private PropertyDescriptorCollection propertyDescriptorCollection = new PropertyDescriptorCollection(null);

        #endregion
    
        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 속성 설명자 컬렉션 - Properties

        /// <summary>
        /// 속성 설명자 컬렉션
        /// </summary>
        public PropertyDescriptorCollection Properties
        {
            get
            {
                return this.propertyDescriptorCollection;
            }
        }

        #endregion
    
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 아이템 속성들 구하기 - GetItemProperties(propertyDescriptorArray)

        /// <summary>
        /// 아이템 속성들 구하기
        /// </summary>
        /// <param name="propertyDescriptorArray">속성 설명자 배열</param>
        /// <returns>속성 설명자 컬렉션</returns>
        public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] propertyDescriptorArray)
        {
            if(propertyDescriptorArray != null && propertyDescriptorArray.Length > 0)
            {
                return System.Windows.Forms.ListBindingHelper.GetListItemProperties(propertyDescriptorArray[0].PropertyType);
            }
            else
            {
                return this.propertyDescriptorCollection;
            }
        }

        #endregion
    
        #region 리스트명 구하기 - GetListName(propertyDescriptorArray)

        /// <summary>
        /// 리스트명 구하기
        /// </summary>
        /// <param name="propertyDescriptorArray">속성 설명자 배열</param>
        /// <returns>리스트명</returns>
        public string GetListName(PropertyDescriptor[] propertyDescriptorArray)
        {
            return this.ToString();
        }

        #endregion

        #region 추가하기 - Add(item)

        /// <summary>
        /// 추가하기
        /// </summary>
        /// <param name="item">아이템</param>
        public new void Add(T item)
        {
            if(base.Count == 0)
            {
                Type type = item.GetType();

                if(this.propertyDescriptorCollection.Count == 0)
                {
                    foreach(MemberInfo memberInfo in type.GetMembers())
                    {
                        switch(memberInfo.MemberType)
                        {
                            case MemberTypes.Field :

                                FieldInfo fieldInfo = memberInfo as FieldInfo;

                                this.propertyDescriptorCollection.Add
                                (
                                    new TypedPropertyDescriptor<T>
                                    (
                                        fieldInfo.GetValue,
                                        fieldInfo.SetValue,
                                        fieldInfo.Name,
                                        fieldInfo.FieldType
                                    )
                                );
                                
                                break;

                            case MemberTypes.Property :

                                PropertyInfo propertyInfo = memberInfo as PropertyInfo;

                                this.propertyDescriptorCollection.Add
                                (
                                    new TypedPropertyDescriptor<T>
                                    (
                                        propertyInfo.GetValue,
                                        propertyInfo.SetValue,
                                        propertyInfo.Name,
                                        propertyInfo.PropertyType
                                    )
                                );

                                break;
                        }
                    }
                }
                else
                {
                    foreach(PropertyDescriptor propertyDescriptor in this.propertyDescriptorCollection)
                    {
                        MemberInfo[] memberInfo = type.GetMember(propertyDescriptor.Name);

                        if(memberInfo == null || memberInfo.Length == 0)
                        {
                            throw new Exception(propertyDescriptor.Name + "가 존재하지 않습니다.");
                        }
                    }
                }
            }

            base.Add(item);
        }

        #endregion

        #region GetValue 함수 구하기 - GetGetValueFunc(memberName)

        /// <summary>
        /// GetValue 함수 구하기
        /// </summary>
        /// <param name="memberName">멤버명</param>
        /// <returns>GetValue 함수</returns>
        public Func<object, object> GetGetValueFunc(string memberName)
        {
            if(base.Count == 0)
            {
                return null;
            }

            Type type = base[0].GetType();

            FieldInfo fieldInfo = type.GetField(memberName);

            if(fieldInfo != null)
            {
                return fieldInfo.GetValue;
            }
            else
            {
                PropertyInfo propertyInfo = type.GetProperty(memberName);

                if(propertyInfo != null)
                {
                    return propertyInfo.GetValue;
                }

                return null;
            }
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요