디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

최근에 각잡고 짠 구현 코드인데 평가 바람

ㅆㅇㅆ(124.216) 2025.07.30 14:03:27
조회 113 추천 0 댓글 3

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace JDWCodeVault.Patterns.Creational
{
    /// <summary>
    /// 플루언트 빌더 패턴의 기본 인터페이스
    /// 메소드 체이닝을 통한 객체 생성을 지원합니다.
    /// </summary>
    /// <typeparam name="T">생성할 객체의 타입</typeparam>
    public interface IObjectBuilder<T>
    {
        /// <summary>
        /// 속성 값을 설정합니다.
        /// </summary>
        /// <typeparam name="TProperty">속성의 타입</typeparam>
        /// <param name="property">설정할 속성</param>
        /// <param name="value">설정할 값</param>
        /// <returns>빌더 인스턴스 (메소드 체이닝용)</returns>
        IObjectBuilder<T> Configure<TProperty>(Expression<Func<T, TProperty>> property, TProperty value);
       
        /// <summary>
        /// 조건부로 속성 값을 설정합니다.
        /// </summary>
        /// <typeparam name="TProperty">속성의 타입</typeparam>
        /// <param name="condition">설정 조건</param>
        /// <param name="property">설정할 속성</param>
        /// <param name="value">설정할 값</param>
        /// <returns>빌더 인스턴스 (메소드 체이닝용)</returns>
        IObjectBuilder<T> ConfigureIf<TProperty>(bool condition, Expression<Func<T, TProperty>> property, TProperty value);
       
        /// <summary>
        /// 설정된 값들로 최종 객체를 생성합니다.
        /// </summary>
        /// <returns>생성된 객체</returns>
        T Build();
       
        /// <summary>
        /// 빌더를 초기 상태로 리셋합니다.
        /// </summary>
        /// <returns>리셋된 빌더 인스턴스</returns>
        IObjectBuilder<T> Reset();
    }

    /// <summary>
    /// 제네릭 플루언트 빌더 구현체
    /// 리플렉션을 사용하여 동적으로 객체를 생성합니다.
    /// </summary>
    /// <typeparam name="T">생성할 객체의 타입</typeparam>
    public class FluentBuilder<T> : IObjectBuilder<T> where T : class, new()
    {
        private readonly Dictionary<string, object> properties;
        private readonly Dictionary<string, Func<object, bool>> validators;

        public FluentBuilder()
        {
            properties = new Dictionary<string, object>();
            validators = new Dictionary<string, Func<object, bool>>();
        }

        public IObjectBuilder<T> Configure<TProperty>(Expression<Func<T, TProperty>> property, TProperty value)
        {
            var propertyName = GetPropertyName(property);
            properties[propertyName] = value;
            return this;
        }

        public IObjectBuilder<T> ConfigureIf<TProperty>(bool condition, Expression<Func<T, TProperty>> property, TProperty value)
        {
            if (condition)
            {
                Configure(property, value);
            }
            return this;
        }

        /// <summary>
        /// 속성에 대한 검증 규칙을 추가합니다.
        /// </summary>
        /// <typeparam name="TProperty">속성의 타입</typeparam>
        /// <param name="property">검증할 속성</param>
        /// <param name="validator">검증 함수</param>
        /// <returns>빌더 인스턴스</returns>
        public FluentBuilder<T> AddValidator<TProperty>(Expression<Func<T, TProperty>> property, Func<TProperty, bool> validator)
        {
            var propertyName = GetPropertyName(property);
            validators[propertyName] = obj => validator((TProperty)obj);
            return this;
        }

        public T Build()
        {
            ValidateProperties();
           
            var instance = new T();
            var type = typeof(T);

            foreach (var kvp in properties)
            {
                var propertyInfo = type.GetProperty(kvp.Key);
                if (propertyInfo != null && propertyInfo.CanWrite)
                {
                    propertyInfo.SetValue(instance, kvp.Value);
                }
            }

            return instance;
        }

        public IObjectBuilder<T> Reset()
        {
            properties.Clear();
            return this;
        }

        private void ValidateProperties()
        {
            foreach (var kvp in properties)
            {
                if (validators.TryGetValue(kvp.Key, out var validator))
                {
                    if (!validator(kvp.Value))
                    {
                        throw new ArgumentException($"Validation failed for property: {kvp.Key}");
                    }
                }
            }
        }

        private static string GetPropertyName<TProperty>(Expression<Func<T, TProperty>> property)
        {
            if (property.Body is MemberExpression memberExpression)
            {
                return memberExpression.Member.Name;
            }
            throw new ArgumentException("Expression must be a property access", nameof(property));
        }
    }

    /// <summary>
    /// 단계별 빌더 패턴을 위한 타입 안전한 빌더
    /// 컴파일 타임에 필수 속성 설정을 강제합니다.
    /// </summary>
    /// <typeparam name="T">생성할 객체의 타입</typeparam>
    public class StepBuilder<T> where T : class
    {
        protected readonly Dictionary<string, object> properties;

        protected StepBuilder()
        {
            properties = new Dictionary<string, object>();
        }

        protected StepBuilder(Dictionary<string, object> existingProperties)
        {
            properties = new Dictionary<string, object>(existingProperties);
        }

        protected TNext CreateNext<TNext>() where TNext : StepBuilder<T>, new()
        {
            var next = new TNext();
            foreach (var kvp in properties)
            {
                next.properties[kvp.Key] = kvp.Value;
            }
            return next;
        }
    }

    /// <summary>
    /// 불변 객체 생성을 위한 빌더
    /// 빌드 시점에 모든 속성이 설정된 불변 객체를 생성합니다.
    /// </summary>
    /// <typeparam name="T">생성할 불변 객체의 타입</typeparam>
    public class ImmutableBuilder<T> : IObjectBuilder<T> where T : class
    {
        private readonly Dictionary<string, object> properties;
        private readonly Func<Dictionary<string, object>, T> factory;

        public ImmutableBuilder(Func<Dictionary<string, object>, T> factory)
        {
            this.factory = factory ?? throw new ArgumentNullException(nameof(factory));
            properties = new Dictionary<string, object>();
        }

        public IObjectBuilder<T> Configure<TProperty>(Expression<Func<T, TProperty>> property, TProperty value)
        {
            var propertyName = GetPropertyName(property);
            properties[propertyName] = value;
            return this;
        }

        public IObjectBuilder<T> ConfigureIf<TProperty>(bool condition, Expression<Func<T, TProperty>> property, TProperty value)
        {
            if (condition)
            {
                Configure(property, value);
            }
            return this;
        }

        public T Build()
        {
            return factory(new Dictionary<string, object>(properties));
        }

        public IObjectBuilder<T> Reset()
        {
            properties.Clear();
            return this;
        }

        private static string GetPropertyName<TProperty>(Expression<Func<T, TProperty>> property)
        {
            if (property.Body is MemberExpression memberExpression)
            {
                return memberExpression.Member.Name;
            }
            throw new ArgumentException("Expression must be a property access", nameof(property));
        }
    }

    /// <summary>
    /// 빌더 팩토리 - 다양한 빌더 타입을 생성합니다.
    /// </summary>
    public static class BuilderFactory
    {
        /// <summary>
        /// 플루언트 빌더를 생성합니다.
        /// </summary>
        /// <typeparam name="T">생성할 객체의 타입</typeparam>
        /// <returns>플루언트 빌더 인스턴스</returns>
        public static FluentBuilder<T> CreateFluent<T>() where T : class, new()
        {
            return new FluentBuilder<T>();
        }

        /// <summary>
        /// 불변 객체 빌더를 생성합니다.
        /// </summary>
        /// <typeparam name="T">생성할 불변 객체의 타입</typeparam>
        /// <param name="factory">객체 생성 팩토리 함수</param>
        /// <returns>불변 객체 빌더 인스턴스</returns>
        public static ImmutableBuilder<T> CreateImmutable<T>(Func<Dictionary<string, object>, T> factory) where T : class
        {
            return new ImmutableBuilder<T>(factory);
        }
    }
} 평가 부탁드립니다.

추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 공개연애가 득보다 실인 것 같은 스타는? 운영자 25/10/06 - -
AD 프로게이머가 될테야!! 운영자 25/10/01 - -
공지 프로그래밍 갤러리 이용 안내 [96] 운영자 20.09.28 47762 65
2895027 시험관아기 = 인체연성실험 = 호문쿨러스 ♥덩냥이♥갤로그로 이동합니다. 13:23 8 0
2895026 너네 샤프 p205 아냐?? 수학쌤샤프 ㅇㅇ(223.38) 13:22 6 0
2895025 직장 생활할때 ai 써도 뭐라 안해요? [1] 프갤러(203.252) 12:58 18 0
2895024 환율 5연속 베팅 성공 chironpractor갤로그로 이동합니다. 12:57 13 0
2895023 네이버 경력 라이브 코테 프갤러(1.232) 12:50 22 0
2895022 자기가 뭘 안다고 생각하는 클라가 제일 피곤하다 [1] 에이도비갤로그로 이동합니다. 12:47 23 0
2895021 [실베펌] 중국의 국제적 위상 chironpractor갤로그로 이동합니다. 12:18 16 0
2895020 내일 출근 할 생각에 심장 떨리면 [7] ㅇㅇ(211.235) 12:07 44 0
2895017 디씨 정책 바껴서 11개월 로긴 안하면 고닉 날려버리네? [8] chironpractor갤로그로 이동합니다. 11:57 44 0
2895016 갤 망했네 예전 갤럼들 없나? [1] 호루스갤로그로 이동합니다. 11:54 24 0
2895015 ㄹㅇ 작고 가벼운 맥북 라인업만 있으면 다 버리고 맥 간다 [2] ♥덩냥이♥갤로그로 이동합니다. 11:40 28 0
2895013 개인적으로 스프링 식 변수명 함수명 씹극혐임 [3] ㅇㅇ(223.39) 11:21 37 0
2895012 요즘도 네이버부스트캠프나 소프트웨어마에스트로 같은곳 [1] ㅇㅇ갤로그로 이동합니다. 11:20 24 0
2895011 디씨 로긴할 때 보안코드는 잃어버리면 고닉 버려야 함? ㅇㅇ(121.168) 10:47 16 0
2895010 그냥 e코어나 lpe코어만 때려박은 모바일칩 나와라 ♥덩냥이♥갤로그로 이동합니다. 10:09 28 0
2895009 인텔 펜서레이크 이후 모바일 로드맵이 안나오네 [1] ♥덩냥이♥갤로그로 이동합니다. 10:03 37 0
2895008 웹디자이너는 돈낭비 아님? [6] ㅇㅇ(39.121) 09:55 57 0
2895007 코딩할때 변수명은 심플한게 좋음 [1] 프갤러(118.38) 09:55 51 0
2895006 님들 진지하게 한국 게임회사 까내리려는거 아니고 [2] ㅇㅇ(182.213) 09:54 44 0
2895005 마라톤 어록 모음 ♥덩냥이♥갤로그로 이동합니다. 09:35 20 0
2895004 코스프레 ♥덩냥이♥갤로그로 이동합니다. 08:52 34 0
2895003 작년 11월 폭설로망한 마트 현재모습 ㅇㅅㅇ [1] 헤르 미온느갤로그로 이동합니다. 08:38 47 0
2895002 태연 ㅇㅅㅇ 헤르 미온느갤로그로 이동합니다. 08:33 21 0
2895001 하루 한 번 헤르미온느 찬양 헤르 미온느갤로그로 이동합니다. 08:32 33 0
2895000 나이가 들어서 그런가 많이 못먹겠다 [2] 류류(122.197) 08:26 35 0
2894999 내년 설에는 도쿄가고 ㅇㅅㅇ 류류(122.197) 08:23 21 0
2894998 ai로 편해진 게 가장 체감되는 영역 [2] ㅇㅇ(223.39) 07:14 65 0
2894997 실명제 sns와 익명제 sns에서 인기 끄는 글들이 거짓일 확률 비교 발명도둑잡기(118.216) 05:44 42 0
2894996 걍 딱 말해준다 윈도우 쓰는 이유 에이도비갤로그로 이동합니다. 05:30 48 0
2894995 운동권 출신 김광석 주변의 이상한 사건들 발명도둑잡기(39.7) 04:58 33 0
2894994 코드로 모션 디테일 맞추려고 하는건 너무 하드하나 루도그담당(58.239) 04:55 24 0
2894993 음기 충전 발명도둑잡기(39.7) 04:40 50 0
2894992 美우주군과 전쟁무기 기업 한화를 은폐한 제주 '우주산업 클러스터' 발명도둑잡기(39.7) 04:19 26 0
2894991 트럼프가 ‘영화 관세’ 100% 꺼낸 진짜 이유 [디브리핑] 발명도둑잡기(39.7) 04:06 29 0
2894990 책 잘 읽음 [5] 따당갤로그로 이동합니다. 03:54 96 0
2894989 기독교 유대교 이슬람교 불교 유교 경전 중 창녀가 언급된 것 발명도둑잡기(39.7) 03:37 31 0
2894986 냥덩이 털사친 글 보니 드는 생각 발명도둑잡기(39.7) 03:00 49 0
2894982 고어사이트 들어갔다가 파일이 저절로 깔림 [4] ㅇㅇ갤로그로 이동합니다. 02:14 85 0
2894981 페이스북 '좋아요'로 사용자 성, 인종, 정치성향, 종교, 지능 발명도둑잡기(39.7) 02:10 34 0
2894980 소라2 예시 발명도둑잡기(39.7) 02:00 28 0
2894978 올해 금리 팍팍떨어진다는데 [1] 방순국갤로그로 이동합니다. 01:57 48 0
2894976 KAIST, 마찰전기 발생 원리 세계 최초로 규명 발명도둑잡기(39.7) 01:49 50 0
2894975 다들 굿나잇⭐ [2] ♥덩냥이♥갤로그로 이동합니다. 01:34 43 0
2894974 공포게임 리뷰지다냥❤+ ♥덩냥이♥갤로그로 이동합니다. 01:32 53 0
2894973 자본가가 저절로 거지 된 사례가 몇%? [1] 발명도둑잡기(39.7) 01:26 40 0
2894972 빈지노-Nike Shoes 관련 생각나는 것 발명도둑잡기(39.7) 01:20 21 0
2894971 와 추석인데도열받네 [1] 프갤러(211.119) 01:17 52 0
2894970 힙합갤러리 버XX가 예전 사람들과 패턴이 달랐던 점 발명도둑잡기(39.7) 01:04 25 0
2894969 난 술만 먹으면 메이플이 하고싶어져... 6개월째 안하고 있는데도... ㅇㅇ(223.38) 01:03 19 0
뉴스 치어리더 권희원, 아이돌 비주얼 화보 공개 “장원영 닮은꼴 미모 눈길” 디시트렌드 10.06
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2