디시인사이드 갤러리

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

갤러리 본문 영역

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

ㅆㅇㅆ(124.216) 2025.07.30 14:03:27
조회 93 추천 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/08/11 - -
AD 가전디지털, 휴대폰 액세서리 SALE 운영자 25/08/08 - -
2877252 애저가 맞긴한데 아주르로 읽어도됨 ㅆㅇㅆ(124.216) 08.02 52 0
2877251 MS azure 는 아주르 아니고 "애저" 라고 읽는데 [6] 프갤러(183.101) 08.02 92 0
2877247 우리집 ㄱㄱㄱㄱ 프갤러(220.86) 08.02 138 1
2877246 멍유 2차흑화하면 닉 이걸로 바꾸냐? [1] 프갤러(119.71) 08.02 66 0
2877244 드디어 아주르 아키텍쳐 패턴 다읽었다 [11] ㅆㅇㅆ(124.216) 08.02 105 0
2877243 석열이햄 빤쓰쇼는 사실 뭐 할 수 있다고 보이긴함 [2] ㅆㅇㅆ(124.216) 08.02 94 0
2877242 멍유가 저리 망가진것도 결국 나님 때문이겠지.. [7] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.02 104 0
2877241 윤석열 빤스쇼 나도 보도싶구나 [1] 헬마스터갤로그로 이동합니다. 08.02 91 1
2877240 내일 아니 애널 뛰뛰 하려했는데 그냥 쉬어야할듯 [2] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.02 79 0
2877238 ..갔오? [1] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.02 70 0
2877237 저딴 게 일국의 머통령이었다니 ㅋㅋㅋㅋ [1] 아스카영원히사랑해갤로그로 이동합니다. 08.02 105 0
2877236 3년뒤에 SRE로 직무 변경할건데 기술 스택 평가좀요 프갤러(153.246) 08.02 49 0
2877235 당신이 먹는것들이 곧 당신이당 By 나님 [1] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.02 63 0
2877234 힘을 원하는가? [1] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.02 65 0
2877233 프로그래밍은 왜 애들이 문서를 안읽냐 [1] ㅆㅇㅆ찡갤로그로 이동합니다. 08.02 103 0
2877232 밤샘 작업 매우 힘들구나 아스카영원히사랑해갤로그로 이동합니다. 08.02 67 0
2877230 윤석열 오늘 상황.jpg [6] 야옹아저씨갤로그로 이동합니다. 08.02 607 9
2877228 ㅅㅂ 모기 느낌 때문에 자꾸 불 껏다켯다 하니까 지치넹.. [1] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 59 0
2877227 돈벌기 어렵네 프갤러(118.235) 08.01 65 0
2877225 누가 제발 저 모기 같은 멍퀴 좀 처리 좀 해주라.. [6] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 90 0
2877224 사무직노동자가 되는길은 멀고도 험하구나 ㅇㅇ(14.52) 08.01 51 0
2877222 분명 모기 있는데.. 미치겟넹.. 모기약에도 안 죽엇낭.. [2] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 66 0
2877221 오늘부터 사이타마 운동법을 할 예정이다 [5] ㅆㅇㅆ(124.216) 08.01 77 0
2877220 컴활1급 딴사람 있음? [1] ㅇㅇ(14.52) 08.01 62 0
2877217 몸상태가 나을듯 말듯 [1] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 62 0
2877216 남자가 군대가는건 지극히 당연하고 오히려 감사해야 할일임 프갤러(115.138) 08.01 58 0
2877215 코파일럿 버그 많네 [1] 프갤러(175.213) 08.01 70 1
2877213 뉴프로에 사용자 많이 유입됐더라 헬마스터갤로그로 이동합니다. 08.01 61 0
2877212 나님 조만간 프갤러 분석 특집 칼럼 써주겠음 1편 대상자는 [4] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 73 0
2877210 얘들아 나 ㄹㅇ 어떡함? 진짜 좆됐는데 씨발 [5] 프갤러(211.202) 08.01 105 0
2877207 해킹 할줄 알려면 뭐배워야됨? [1] ㅇㅇ(118.235) 08.01 72 0
2877205 ㅅㅂ 일찍 자려구 했는데 모기약 빼느라 못 자구있다 ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 44 0
2877202 모기약 뿌리면 머리 아파서 되도록이면 안 뿌리는댕.. ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 45 0
2877197 프로그래밍도 그림이나 악기같은거처럼 많이 하면 느냐 프갤러(211.192) 08.01 58 0
2877193 요즘 모기 못 봤다고 방심 했더니 바로 나타나넹.. ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 44 0
2877192 아스카 작업 중 커뮤니케이션 미스로 실수함 아스카영원히사랑해갤로그로 이동합니다. 08.01 64 0
2877190 나님 개좃됨.. ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 49 0
2877184 자료구조라는건 어떻게 공부하는거에요? 저 3문제푸는데 9시간걸리는데 [2] ㅇㅇ(223.39) 08.01 61 0
2877181 하루에 천억줄 감사의 코딩 공기역학갤로그로 이동합니다. 08.01 53 0
2877179 모두 냥덩이를 위해 기도 해주세양.. [3] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 83 0
2877176 주민등록 사실조사 참여 안하면 과태료 50만원 부과 될 수도 잇다네 [5] 야옹아저씨갤로그로 이동합니다. 08.01 431 8
2877173 나님 건강 이슈로 당분간 탈갤합니당.. [1] ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 83 0
2877172 구글창업자: 세르게이 - 잼민이ai 금지한사람 골때린다 프갤러(183.101) 08.01 58 0
2877169 열돔은 콘돔이당 By 나님 ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 58 0
2877164 코딩 뉴비 조언좀요 ㅠㅠ 프갤러(118.235) 08.01 81 0
2877162 나님 애널두 무사히 차분하게 주무실 준비..⭐+ ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 60 0
2877161 잠 한번 잘못잤다고 멀미 비스무리하게 오는둣? ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 46 0
2877158 리버스 만유인력? ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 52 0
2877157 오호라 음의 유효질량.. ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 45 0
2877156 피궁해서 누엇당.. 졸리.. ♥찢명아티스트냥덩♥갤로그로 이동합니다. 08.01 44 0
뉴스 홍진경 맞아? 22년 만에 이혼 발표…백발로 변신한 근황 디시트렌드 08.12
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2