프로그래밍 기술/Windows Form 응용 프로그램

4.3 엔진 개발 [Windows Forms 응용 프로그램]

언제나휴일 2016. 4. 6. 13:00
반응형

4.3 엔진 개발

 

 이제 도서 관리자 응용의 엔진을 개발합시다. 폼을 제외한 나머지 부분을 여기에서는 엔진이라고 부를게요.

 

4.3.1 BookStory

 

 도서 정보는 BookStory 클래스로 정의합시다. BookStory 클래스는 차후에 라이브러리 형태로 만들어 제공할 수 있는 형식입니다. 접근 지정을 public 으로 설정한 부분은 라이브러리 형태로 만들 때 외부 프로젝트에서 접근할 수 있게 설정한 것입니다.

public class BookStory

{

 도서의 일련 번호는 읽기 전용 멤버로 선언합니다.

    readonly int seqno;//도서 일련 번호

도서 일련 번호를 가져오기 있는 속성을 제공합니다.

    public int No

    {

        get

        {

            return seqno;

        }

    }

 도서 제목을 가져오기 있는 속성을 제공합니다.

    public string Title

    {

        get;

        private set;

    }

 설명을 가져오기 있는 속성을 제공합니다.

    public string Description

    {

        get;

        set;

    }

 도서 이미지 파일의 이름을 가져오기 설정하기 속성을 제공합니다.

    public string ImageName

    {

        get;

        set;

    }

 날짜를 가져오기 설정하기 속성을 제공합니다.

    public DateTime DT

    {

        get;

        set;

    }

 도서 정보를 입력 인자로 받아 속성을 설정하는 생성자를 제공합니다.

    public BookStory(int no, string title,

            string description, string imagename, DateTime dt)

    {

        seqno = no;

        Title = title;

        Description = description;

        ImageName = imagename;

        DT = dt;

    }

 ToString 메서드를 재정의하여 일련 번호를 문자열로 변환하여 반환합니다.

    public override string ToString()

    {

        return No.ToString();

    }

}

 

 

 

//BookStory.cs

using System;

namespace MyReadingStory

{

    /// <summary>

    /// 도서 클래스

    /// </summary>

    public class BookStory

    {

        #region 멤버 필드 속성

        readonly int seqno;//도서 일련 번호

        /// <summary>

        /// 도서 일련 번호 - 가져오기

        /// </summary>

        public int No

        {

            get

            {

                return seqno;

            }

        }

        /// <summary>

        /// 도서 제목 - 가져오기

        /// </summary>

        public string Title

        {

            get;

            private set;

        }

        /// <summary>

        /// 설명 - 가져오기 설정하기

        /// </summary>

        public string Description

        {

            get;

            set;

        }

        /// <summary>

        /// 이미지 이름 - 가져오기 설정하기

        /// </summary>

        public string ImageName

        {

            get;

            set;

        }

        /// <summary>

        /// 날짜 - 가져오기 설정하기

        /// </summary>

        public DateTime DT

        {

            get;

            set;

        }

        #endregion

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="no">일련 번호</param>

        /// <param name="title">제목</param>

        /// <param name="description">설명</param>

        /// <param name="imagename">이미지 이름</param>

        /// <param name="dt">날짜</param>

        public BookStory(int no, string title,

            string description, string imagename, DateTime dt)

        {

            seqno = no;

            Title = title;

            Description = description;

            ImageName = imagename;

            DT = dt;

        }

        /// <summary>

        /// 재정의

        /// </summary>

        /// <returns>일련번호를 변환한 문자열</returns>

        public override string ToString()

        {

            return No.ToString();

        }

    }

}

 

4.3.2 AddEventArgs, AddEventHandler

 

 도서 관리자 개체에서 도서를 추가하면 게시하는 이벤트를 위해 이벤트 인자와 대리자를 정의합시다.

 

 먼저 추가 이벤트 인자 클래스를 정의합니다. 이벤트 인자를 정의할 때는 EventArgs 클래스를 기반으로 파생 클래스로 정의하는 것을 권장합니다.

public class AddEventArgs:EventArgs

{

 도서를 추가한 것인지 여부를 속성으로 제공합시다. 도서를 추가할 때는 true 삭제할 때는 false입니다.

    public bool IsAdded

    {

        get;

        private set;

    }

 도서 개체를 가져오기 있는 속성을 제공합니다.

    public BookStory BS

    {

        get;

        private set;

    }

 제목을 가져오기 있는 속성을 제공합니다. 도서 개체를 속성으로 제공하여 이러한 속성이 불필요하게 보일 있습니다. 이벤트 인자 형식을 정의할 때는 이벤트 핸들러에서 사용하기 쉽게 속성을 정의하세요.

    public string Title

    {

        get

        {

            return BS.Title;

        }

    }

 일련 번호를 가져오기 있는 속성을 제공합니다.

    public int No

    {

        get

        {

            return BS.No;

        }

   }

 설명을 가져오기 있는 속성을 제공합니다.

    public string Description

    {

        get

        {

            return BS.Description;

        }

    }

 이미지 이름을 가져오기 있는 속성을 제공합니다.

    public string ImageName

    {

        get

        {

            return BS.ImageName;

        }

    }

 날짜를 가져오기 있는 속성을 제공합니다.

    public DateTime DT

    {

        get

        {

            return BS.DT;

        }

    }

 생성자는 도서 개체와 추가/삭제 여부를 입력 인자로 받아 속성을 설정합니다.

    internal AddEventArgs(BookStory bs, bool is_added)

    {

        BS = bs;

        IsAdded = is_added;

    }

}

이벤트 핸들러를 위임할 대리자 형식을 정의합니다.

public delegate void AddEventHandler(object sender, AddEventArgs e);

 

//AddEventArgs.cs

using System;

namespace MyReadingStory

{

    /// <summary>

    /// 도서 추가 이벤트 인자 클래스

    /// </summary>

    public class AddEventArgs:EventArgs

    {

        /// <summary>

        /// 도서를 추가 여부 - 가져오기

        /// </summary>

        public bool IsAdded

        {

            get;

            private set;

        }

        /// <summary>

        /// 도서 - 가져오기

        /// </summary>

        public BookStory BS

        {

            get;

            private set;

        }

        /// <summary>

        /// 도서 제목 - 가져오기

        /// </summary>

        public string Title

        {

            get

            {

                return BS.Title;

            }

        }

        /// <summary>

        /// 도서 일련 번호 - 가져오기

        /// </summary>

        public int No

        {

            get

            {

                return BS.No;

            }

        }

        /// <summary>

        /// 도서 설명 - 가져오기

        /// </summary>

        public string Description

        {

            get

            {

                return BS.Description;

            }

        }

        /// <summary>

        /// 이미지 이름 - 가져오기

        /// </summary>

        public string ImageName

        {

            get

            {

                return BS.ImageName;

            }

        }

        /// <summary>

        /// 날짜 - 가져오기

        /// </summary>

        public DateTime DT

        {

            get

            {

                return BS.DT;

            }

        }

        internal AddEventArgs(BookStory bs, bool is_added)

        {

            BS = bs;

            IsAdded = is_added;

        }

    }

    /// <summary>

    /// 도서 추가 이벤트 핸들러를 위임할 대리자

    /// </summary>

    /// <param name="sender">이벤트 게시자</param>

    /// <param name="e">이벤트 인자</param>

    public delegate void AddEventHandler(object sender, AddEventArgs e);

}

 

4.3.3 ModifyEventArgs, ModifyEventHandler

 

 도서 관리자 개체에서 도서를 변경하면 게시하는 이벤트를 위해 이벤트 인자와 대리자를 정의합시다.

public class ModifyEventArgs : EventArgs

{

 도서 개체를 가져오기 있는 속성을 제공합니다.

    public BookStory BS

    {

        get;

        private set;

    }

 제목을 가져오기 있는 속성을 제공합니다.

    public string Title

    {

        get

        {

            return BS.Title;

        }

    }

 일련 번호를 가져오기 있는 속성을 제공합니다.

    public int No

    {

        get

        {

            return BS.No;

        }

    }

 설명을 가져오기 있는 속성을 제공합니다.

    public string Description

    {

        get

        {

            return BS.Description;

        }

    }

 이미지 파일 이름을 가져오기 있는 속성을 제공합니다.

    public string ImageName

    {

        get

        {

            return BS.ImageName;

        }

    }

 날짜를 가져오기 있는 속성을 제공합니다.

    public DateTime DT

    {

        get

        {

            return BS.DT;

        }

    }

 생성자는 도서 개체를 입력 인자로 받아 속성을 설정합니다.

    internal ModifyEventArgs(BookStory bs)

    {

        BS = bs;

    }

}

 도서 변경 이벤트 핸들러를 위임할 대리자 형식을 정의합니다.

public delegate void ModifyEventHandler(object sender, ModifyEventArgs e);

 

//ModifyEventArgs.cs

using System;

namespace MyReadingStory

{  

    /// <summary>

    /// 도서 변경 이벤트 인자

    /// </summary>

    public class ModifyEventArgs : EventArgs

    {

        /// <summary>

        /// 도서 - 가져오기

        /// </summary>

        public BookStory BS

        {

            get;

            private set;

        }

        /// <summary>

        /// 제목 - 가져오기

        /// </summary>

        public string Title

        {

            get

            {

                return BS.Title;

            }

        }

        /// <summary>

        /// 일련번호 - 가져오기

        /// </summary>

        public int No

        {

            get

            {

                return BS.No;

            }

        }

        /// <summary>

        /// 설명 - 가져오기

        /// </summary>

        public string Description

        {

            get

            {

                return BS.Description;

            }

        }

        /// <summary>

        /// 이미지 이름 - 가져오기

        /// </summary>

        public string ImageName

        {

            get

            {

                return BS.ImageName;

            }

        }

        /// <summary>

        /// 날짜 - 가져오기

        /// </summary>

        public DateTime DT

        {

            get

            {

                return BS.DT;

            }

        }

        internal ModifyEventArgs(BookStory bs)

        {

            BS = bs;

        }

    }

    /// <summary>

    /// 도서 변경 이벤트 핸드러를 위임할 대리자

    /// </summary>

    /// <param name="sender">이벤트 게시자</param>

    /// <param name="e">이벤트 인자</param>

    public delegate void ModifyEventHandler(object sender, ModifyEventArgs e);

}

 


4.3.4 BookManager

 

 폼과 상호작용하여 사용자의 요청에 따라 도서 개체를 관리하고 도서 추가와 삭제, 변경을 수행할 구독자에게 이벤트를 게시하는 등의 프로그램의 주요한 제어 기능을 담당하는 BookManager 클래스를 정의합시다.

class BookManager

{

 도서 개체의 일련 번호는 순차적으로 부여합니다. 일련 번호를 부여하기 위한 멤버를 선언하세요.

    int next_bs_no = 1;

 도서 일련 번호를 키로 하고 도서 개체를 값으로 하는 사전 개체를 생성합니다.

    Dictionary<int, BookStory> bdic = new Dictionary<int, BookStory>();

 도서 추가/삭제 이벤트를 멤버로 선언합니다.

    internal event AddEventHandler OnAddBS = null;

 도서 변경 이벤트를 멤버로 선언합니다.

    internal event ModifyEventHandler OnModifyBS = null;

 도서 관리자 개체는 응용 프로그램에 유일하지 않으면 폼마다 서로 다른 도서 관리자 개체와 상호 작용하게 구현하는 실수를 범할 있습니다. 하나의 도서 관리자 개체를 사용해야 폼들 사이에 상호 작용에 버그가 발생할 확률을 줄일 있으니 단일체 패턴을 적용하기로 합시다.

    #region 단일체 표현

 도서 관리자 단일체를 위한 정적 멤버를 선언합니다.

    static BookManager bm = null;

 도서 관리자 단일체를 가져오기 있는 속성을 제공합니다.

    internal static BookManager BM

    {

        get

        {

            return bm;

        }

    }

 정적 생성자에서 단일체를 생성합니다.

    static BookManager()

    {

        bm = new BookManager();

    }

 생성자의 접근 지정을 private으로 설정하여 다른 클래스에서 도서 관리자 개체를 생성할 없게 합니다.

    private BookManager()

    {

    }

   #endregion

 도서를 추가하는 기능을 제공합니다.

    internal bool AddBook(string title, string description, int no,

                                   string imagename,DateTime dt)

    {

 먼저 같은 일련 번호를 갖는 도서 개체가 있는지 확인합니다. 만약 있다면 false 반환합니다.

        if (bdic.ContainsKey(no))

        {

            return false;

        }

 도서 개체를 생성하여 사전 개체에 추가합니다.

        bdic[no] = new BookStory(no, title, description, imagename, dt);

 다음에 부여할 도서 일련 번호를 1 증가합니다.

        next_bs_no++;

 도서 추가/삭제 이벤트 구독자가 있으면 이벤트를 게시합니다.

        if (OnAddBS != null)

        {

            OnAddBS(this,new AddEventArgs(bdic[no],true));

        }

 성공을 반환합니다.

        return true;

    }

 도서 일련 번호 목록을 구하는 메서드를 제공합시다.

    internal List<int> GetNoColloction()

    {

 도서 일련 번호를 보관할 컬렉션 개체를 생성합니다.

        List<int> list = new List<int>();

 사전 개체의 목록의 일련 번호를 컬렉션에 추가합니다.

        foreach (int no in bdic.Keys)

        {

            list.Add(no);

        }

 컬렉션을 반환합니다.

        return list;

    }

 일련 번호로 도서 검색 기능을 제공합시다.

    internal BookStory FindBook(int no)

    {

 사전 개체에 일련 번호가 없으면 예외를 던집니다. 개발 단계의 버그를 빠르게 발견하기 위해서도 예외 처리를 사용할 있습니다.

        if (bdic.ContainsKey(no)==false)

        {

            throw new ApplicationException("없는 일련 번호로 도서 검색 요청");

        }

 사전 개체의 인덱스 연산으로 도서 개체를 반환합니다.

        return bdic[no];

    }

 다음에 부여할 일련 번호를 확인하는 메서드를 제공합시다.

    internal int NextBSNo()

    {

        return next_bs_no;

    }

 일련 번호로 도서 삭제 기능을 제공합시다.

    internal void RemoveBS(int no)

    {

 사전 개체에 존재하지 않으면 예외를 던집니다.

        if (bdic.ContainsKey(no)==false)

        {

            throw new ApplicationException("없는 번호 삭제하래. 사용해라.");

        }

 사전 개체에서 도서 개체를 구하여 사전 개체에서 제거합니다.

        BookStory bs = bdic[no];

        bdic.Remove(no);

 도서 추가/삭제 이벤트 구독자가 있으면 이벤트를 게시합니다.

        if (OnAddBS != null)

        {

            OnAddBS(this, new AddEventArgs(bs, false));

        }

    }

 도서 목록을 구하는 메서드를 제공합시다.

    internal List<BookStory> GetBSCollection()

    {

 도서 개체를 보관할 컬렉션 개체를 생성합니다.

        List<BookStory> bsl = new List<BookStory>();

 사전 개체의 목록의 도서 개체를 컬렉션에 보관한 컬렉션 개체를 반환합니다.

        foreach(BookStory bs in bdic.Values)

        {

            bsl.Add(bs);

        }

        return bsl;

    }

 도서 정보를 변경하는 메서드를 제공합시다.

    internal void ModifyBS(int no, string description, string imagename,

                                   DateTime dt)

    {

 사전 개체에 일련 번호가 있는지 확인합니다.

        if (bdic.ContainsKey(no))

        {

 있을 사전 개체에서 일련 번호로 도서 개체를 찾습니다.

            BookStory bs = bdic[no];

 입력 인자로 도서 개체의 속성을 설정합니다.

            bs.Description = description;

            bs.ImageName = imagename;

            bs.DT = dt;

 도서 변경 이벤트 구독자가 있으면 이벤트를 게시합니다.

            if (OnModifyBS != null)

            {

                OnModifyBS(this, new ModifyEventArgs(bs));

            }

        }

    }

}

 

using System;

using System.Collections.Generic;

 

namespace MyReadingStory

{   

    class BookManager

    {

        int next_bs_no = 1;

        Dictionary<int, BookStory> bdic = new Dictionary<int, BookStory>();

        /// <summary>

        /// 도서 추가 이벤트

        /// </summary>

        internal event AddEventHandler OnAddBS = null;

        /// <summary>

        /// 도서 변경 이벤트

        /// </summary>

        internal event ModifyEventHandler OnModifyBS = null;

        #region 단일체 표현

        static BookManager bm = null;

        /// <summary>

        /// 도서 관리자 단일체 - 가져오기

        /// </summary>

        internal static BookManager BM

        {

            get

            {

                return bm;

            }

        }

        static BookManager()

        {

            bm = new BookManager();

        }

        private BookManager()

        {

        }

        #endregion

 

        internal bool AddBook(string title, string description, int no,

                                       string imagename,DateTime dt)

        {

            if (bdic.ContainsKey(no))

            {

                return false;

            }

            bdic[no] = new BookStory(no, title, description, imagename, dt);

            next_bs_no++;

            if (OnAddBS != null)

            {

                OnAddBS(this,new AddEventArgs(bdic[no],true));

            }

            return true;

        }

 

        internal List<int> GetNoColloction()

        {

            List<int> list = new List<int>();

            foreach (int no in bdic.Keys)

            {

                list.Add(no);

            }

            return list;

        }

        internal BookStory FindBook(int no)

        {

            if (bdic.ContainsKey(no)==false)

            {

                throw new ApplicationException("없는 일련 번호로 도서 검색 요청");

            }

            return bdic[no];

        }

        internal int NextBSNo()

        {

            return next_bs_no;

        }

        internal void RemoveBS(int no)

        {

            if (bdic.ContainsKey(no)==false)

            {

                throw new ApplicationException("없는 일련 번호로 도서 삭제 요청");

            }

            BookStory bs = bdic[no];

            bdic.Remove(no);

            if (OnAddBS != null)

            {

                OnAddBS(this, new AddEventArgs(bs, false));

            }

        }

        internal List<BookStory> GetBSCollection()

        {

            List<BookStory> bsl = new List<BookStory>();

            foreach(BookStory bs in bdic.Values)

            {

                bsl.Add(bs);

            }

            return bsl;

        }

        internal void ModifyBS(int no, string description, string imagename,

                                       DateTime dt)

        {

            if (bdic.ContainsKey(no))

            {

                BookStory bs = bdic[no];

                bs.Description = description;

                bs.ImageName = imagename;

                bs.DT = dt;

                if (OnModifyBS != null)

                {

                    OnModifyBS(this, new ModifyEventArgs(bs));

                }

            }

        }

    }

}

 

반응형