첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

▶ Program.cs

using System;

namespace TestProject
{
    /// <summary>
    /// 프로그램
    /// </summary>
    class Program
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 프로그램 시작하기 - Main()

        /// <summary>
        /// 프로그램 시작하기
        /// </summary>
        private static void Main()
        {
            Console.WriteLine
            (
                "01".Match()
                    .AddCase(s => s == "01", "홍길동")
                    .AddCase(s => s == "02", "김철수")
                    .AddCase(s => s == "03", "최영희")
                    .AddElseCase("무명씨")
                    .Execute()
            );
        }

        #endregion
    }
}

 

▶ IncompletePatternMatchException.cs

using System;

namespace TestProject
{
    /// <summary>
    /// 불완전 패턴 매치 예외
    /// </summary>
    public class IncompletePatternMatchException : Exception
    {
    }
}

 

▶ PatternMatchValue.cs

using System;
using System.Collections.Generic;

namespace TestProject
{
    /// <summary>
    /// 패턴 매치 값
    /// </summary>
    /// <typeparam name="TSource">소스 타입</typeparam>
    /// <typeparam name="TResult">결과 타입</typeparam>
    public class PatternMatchValue<TSource, TResult>
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 패턴 매치 케이스 - PatternMatchCase

        /// <summary>
        /// 패턴 매치 케이스
        /// </summary>
        private struct PatternMatchCase
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region Field

            /// <summary>
            /// 판정 대리자
            /// </summary>
            public Predicate<TSource> Predicate;

            /// <summary>
            /// 결과 함수
            /// </summary>
            public Func<TSource, TResult> ResultFunction;

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 소스
        /// </summary>
        private readonly TSource source;

        /// <summary>
        /// 패턴 매치 케이스 리스트
        /// </summary>
        private readonly IList<PatternMatchCase> list = new List<PatternMatchCase>();

        /// <summary>
        /// ELSE 케이스 함수
        /// </summary>
        private Func<TSource, TResult> elseCaseFunction;

        #endregion

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

        #region 생성자 - PatternMatchValue(source)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="source">소스</param>
        public PatternMatchValue(TSource source)
        {
            this.source = source;
        }

        #endregion

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

        #region 케이스 추가하기 - AddCase(predicate, result)

        /// <summary>
        /// 케이스 추가하기
        /// </summary>
        /// <param name="predicate">판정 대리자</param>
        /// <param name="result">결과</param>
        /// <returns>패턴 매치 값</returns>
        public PatternMatchValue<TSource, TResult> AddCase(Predicate<TSource> predicate, TResult result)
        {
            return AddCase(predicate, x => result);
        }

        #endregion
        #region 케이스 추가하기 - AddCase(predicate, resultFunction)

        /// <summary>
        /// 케이스 추가하기
        /// </summary>
        /// <param name="predicate">판정 대리자</param>
        /// <param name="resultFunction">결과 함수</param>
        /// <returns>패턴 매치 값</returns>
        public PatternMatchValue<TSource, TResult> AddCase
        (
            Predicate<TSource>     predicate,
            Func<TSource, TResult> resultFunction
        )
        {
            list.Add
            (
                new PatternMatchCase
                {
                    Predicate      = predicate,
                    ResultFunction = resultFunction
                }
            );

            return this;
        }

        #endregion

        #region ELSE 케이스 추가하기 - AddElseCase(result)

        /// <summary>
        /// ELSE 케이스 추가하기
        /// </summary>
        /// <param name="result">결과</param>
        /// <returns>패턴 매치 값</returns>
        public PatternMatchValue<TSource, TResult> AddElseCase(TResult result)
        {
            return AddElseCase(x => result);
        }

        #endregion
        #region ELSE 케이스 추가하기 - AddElseCase(resultFunction)

        /// <summary>
        /// ELSE 케이스 추가하기
        /// </summary>
        /// <param name="resultFunction">결과 함수</param>
        /// <returns>패턴 매치 값</returns>
        public PatternMatchValue<TSource, TResult> AddElseCase(Func<TSource, TResult> resultFunction)
        {
            if(this.elseCaseFunction != null)
            {
                throw new InvalidOperationException("Cannot have multiple else cases");
            }

            this.elseCaseFunction = resultFunction;

            return this;
        }

        #endregion

        #region 실행하기 - Execute()

        /// <summary>
        /// 실행하기
        /// </summary>
        /// <returns>결과</returns>
        public TResult Execute()
        {
            if(this.elseCaseFunction != null)
            {
                AddCase(x => true, this.elseCaseFunction);

                this.elseCaseFunction = null;
            }

            foreach(PatternMatchCase @case in this.list)
            {
                if(@case.Predicate(source))
                {
                    return @case.ResultFunction(source);
                }
            }

            throw new IncompletePatternMatchException();
        }

        #endregion
    }
}

 

▶ PatternMatchContext.cs

using System;

namespace TestProject
{
    /// <summary>
    /// 패턴 매치 컨텍스트
    /// </summary>
    /// <typeparam name="TSource">소스 타입</typeparam>
    public class PatternMatchContext<TSource>
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 소스
        /// </summary>
        private readonly TSource source;

        #endregion

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

        #region 생성자 - PatternMatchContext(source)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="source">소스</param>
        public PatternMatchContext(TSource source)
        {
            this.source = source;
        }

        #endregion

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

        #region 케이스 추가하기 - AddCase<TResult>(predicate, result)

        /// <summary>
        /// 케이스 추가하기
        /// </summary>
        /// <typeparam name="TResult">결과 타입</typeparam>
        /// <param name="predicate">판정 대리자</param>
        /// <param name="result">결과</param>
        /// <returns>패턴 매치 값</returns>
        public PatternMatchValue<TSource, TResult> AddCase<TResult>(Predicate<TSource> predicate, TResult result)
        {
            return new PatternMatchValue<TSource, TResult>(source).AddCase(predicate, result);
        }

        #endregion
    }
}

 

▶ PatternMatchExtension.cs

namespace TestProject
{
    /// <summary>
    /// 패턴 매치 확장
    /// </summary>
    public static class PatternMatchExtension
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 매치하기 - Match(value)

        /// <summary>
        /// 매치하기
        /// </summary>
        /// <typeparam name="TSource">소스 타입</typeparam>
        /// <param name="source">소스</param>
        /// <returns>패턴 매치 컨텍스트</returns>
        public static PatternMatchContext<TSource> Match<TSource>(this TSource source)
        {
            return new PatternMatchContext<TSource>(source);
        }

        #endregion
    }
}
728x90
반응형
Posted by 사용자 icodebroker

댓글을 달아 주세요