Microsoft MVP성태의 닷넷 이야기
리플렉션 성능 관련 질문 드립니다. [링크 복사], [링크+제목 복사]
조회: 14281
글쓴 사람
popo
홈페이지
첨부 파일
 

안녕하세요 다음과 같이 DataTable을 특정 모델 클래스의 List<T>타입으로 Convert해서 사용하고 있습니다.

그런데 성능상 데이터가 많은 편이 아닌데도 느린 부분이 있어 혹시 어디 부분에서 성능이 떨어지는지 도움 요청드립니다.

소스는 다음과 같고, 모델 클래스의 각각 Property에 DataTable의 해더명을 어트리뷰트로 정의해서 자동으로 Property의 타입에 맞게 캐스팅해서 속성을 채우는 방식입니다.

테스트시 DataTable에 약 50개 정도의 Row를 List<T>형식으로 변환 했을때 1s ~ 2s사이 정도 시간이 지연 됬습니다.

소스에 문제가 되는 부분이 있는지 도움 요청 드립니다.

public static List<T> DataTableToList<T>(DataTable table) where T : class, new()
        {
            if (table == null) return null;

            try
            {
                List<T> list = new List<T>();

                foreach (DataRow row in table.AsEnumerable())
                {
                    T obj = new T();

                    foreach (PropertyInfo prop in obj.GetType().GetProperties())
                    {
                        try
                        {
                            string headerCaption = null;

                            // 모델 클래스(T) 속성에 설정되어 있는 어트리뷰트 Get
                            object[] atts = prop.GetCustomAttributes(typeof(ExtensionEnumAttribute), false);
                            if (atts != null && atts.Length <= 0)
                            {
                                continue;
                            }

                            ExtensionEnumAttribute att = (ExtensionEnumAttribute)atts[0];
                            if (att == null || att.Objs == null || att.Objs.Length < 0 || string.IsNullOrWhiteSpace(att.Objs[0].ToString()))
                            {
                                headerCaption = prop.Name;
                            }
                            else
                            {
                                // 속성에 설정되어 있는 컬럼 헤더 타이틀 어리트뷰트 값
                                headerCaption = att.Objs[0].ToString();
                            }

                            PropertyInfo propertyInfo = obj.GetType().GetProperty(prop.Name);

                            if (propertyInfo.PropertyType.IsEnum)
                            {
                                object enumVal = Enum.Parse(propertyInfo.PropertyType, row[headerCaption].ToString());
                                propertyInfo.SetValue(obj, enumVal, null);
                            }
                            else
                            {
                                Type t = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;

                                if (row[headerCaption] != DBNull.Value)
                                {
                                    propertyInfo.SetValue(obj, Convert.ChangeType(row[headerCaption], t), null);
                                }
                                else
                                {
                                    propertyInfo.SetValue(obj, null, null);
                                }
                            }
                        }
                        catch(Exception ex)
                        {
                            // 데이터 테이블에 없는 모델 클래스(T) 속성
                            // 예] IsSelectCheck 속성 등..
                            continue;
                        }
                    }

                    list.Add(obj);
                }

                return list;
            }
            catch(Exception ex)
            {
                throw new Exception("데이터 테이블 -> 모델 변환 오류");
            }
        }








[최초 등록일: ]
[최종 수정일: 5/26/2017]


비밀번호

댓글 작성자
 



2017-05-26 02시32분
직접 재보시는 것이 더 빠르지 않을까요? ^^ Stopwatch 클래스를 이용해 어느 부분에서 시간이 더 걸리는 것인지 밝혀낸 다음 왜 그런지 물어보시면 더 좋을 것 같습니다.

참고로, .NET Reflection은 원래 느립니다. (느리다는 말이 매우 상대적인 기준이긴 하지만.)

아울러 다음의 글들도 한번 읽어보시고.

C# 4.0 - dynamic 키워드
; http://www.sysnet.pe.kr/2/0/766

C# - Reflection의 박싱 없이 값 형식을 다루는 방법
; http://www.sysnet.pe.kr/2/0/10866
정성태
2017-05-26 08시47분
일단 리플렉션을 메서드 사용을 최소화하는 게 중요해 보입니다.
GetProperties() 나 GetCustomAttributes() 같은 것들을 캐쉬 처리할 수 있으면 좋을 것 같습니다.
그리고 정성태님이 열거해주신 링크 중 Reflection의 박싱 없이 값 형식을 다루는 방법...에 나오는 LCG 기법이면 박싱도 해결될테구요.
어떤 방식으로 처리하는지 실제 사례를 확인해보시고 싶으시면 github의 dapper를 fork 하셔서 ormapping 하는 코드를 뒤져보시면 도움이 되지 않을까 싶습니다.
Beren Ko

... 31  32  33  34  35  36  37  38  39  40  41  [42]  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
4796Bere...1/13/201711680++ 후위연산자와 = 을 함께 사용할 때 생성되는 IL 코드 관련... [2]
4795김철환1/11/201712778이벤트 부분을 읽고 있는데 이해가 안되서 질문합니다.. [11]
4794김철환1/10/201710071안녕하세요 c# 6.0 책을 구매한 사람인데요 [3]
4793장준영1/7/201712107안녕하세요 c언어 처음 공부해보는 학생입니다 [4]파일 다운로드1
4792김재영1/4/201713118소스코드 공개 전 성태님의 의견을 듣고싶습니다 [3]
4791C#초보12/28/201612934비동기 소켓 close시 ObjectDisposedException 문제점 질문 있습니다.. [1]
4790미나리12/24/201613170파워포인트 쇼 제어 SimpleHttpServer.cs 작동문제 [4]파일 다운로드1
4789김솔지12/21/201612002프린트 시, 프린트하는 파일의 파일명 구하는 부분에 대해서 질문드립니다. [1]
4788짜두12/19/201611730Visual Studio 2015 에서 msbuild 12 사용 [5]
4787guest12/18/201613531VLC라이브러리에 대해 아시나요? [3]파일 다운로드1
4785Hyou...12/16/201613653WPF 개발 시 MVVM 프레임워크 사용 [2]
4784ds12/15/201610307문의 드립니다. [2]
4783후배12/13/201611909MemoryStream에 관한 질문 입니다. [5]
4782김형민12/6/201610240[ C# 6.0 ] 126p 오타인가요? [6]
4781질문자11/29/201610361ms워드 저장 오류 [1]
4780최진11/28/201614793안녕 하세요 빌드 관련해서 질문드립니다 꾸벅 [4]
4779손니11/28/201611132안녕하세요 질문하다 드려도 될까요 [3]
4778김상호11/25/201610666재귀호출->비재귀호출 [2]파일 다운로드1
4777권오영11/12/201612914아래 질문 상세 소스전체입니다.. [3]
4776권오영11/11/201610836제가 이클립스를 공부중인데..이상한것을 찾았습니다.. [2]
4775이성환11/11/201614282안녕하세요. SnapsToDevicePixels 질문입니다. [5]파일 다운로드1
4774popo11/10/201610902.net SSL통신 관련 질문 드립니다. [1]
4773김상호11/4/201613390재귀함수 반복문 변환 [1]파일 다운로드1
4772자연인10/27/201614382hwpctrl을 사용하는 사이트에서 나와 브라우저를 종료하면 오류메세지가 나옵니다. [1]파일 다운로드1
4771문종훈10/18/201614431.net 소스 질문이 있습니다 [2]
4770누구게~...10/15/201611654세도나 [1]
... 31  32  33  34  35  36  37  38  39  40  41  [42]  43  44  45  ...