1 Stream stream = this.GetType().Assembly.GetManifestResourceStream("WindowsApplication1.filename.jpg");
  2 Bitmap bmp = new Bitmap(stream);

출처 : Microsoft 고객지원

'.Net > C#' 카테고리의 다른 글

C# Serialize, Deserialize  (0) 2012.08.21
C# DoubleBuffering (더블 버퍼링)  (0) 2012.08.07
C# UserControl->UserControl 네이버 지식인 답변  (0) 2012.07.17
C# Thread Test Project  (0) 2012.07.11
C# Image->Bitmap->Icon  (1) 2012.07.04

아래의 글은 언제나 휴일 출판사의 장문석님의 "Escort GoF의 디자인 패턴" 도서의 내용을 정리한 것 입니다. (http://cafe.daum.net/ehclub.net/S8l6/11)

 

원형 패턴(Prototype Pattern)

 

1.1 개요

 

원형 패턴은 미리 만들어진 개체를 복사하여 개체를 생성하는 패턴을 말합니다. 그리고, 이 때 미리 만들어진 개체를 원형 개체라 부릅니다. 일반화 관계로 표현을 할 때 파생클래스의 개수가 과도히 많아지고 각 클래스의 메서드에서 수행하는 알고리즘에 차이가 없고 생성 시에 개체의 속성에 차이만 있다면 원형 패턴을 사용하는 것이 효과적입니다.

 

1.2 시나리오

 

다음 주에는 거제도와 통영으로 2박 3일 여행을 가기로 하였습니다. 그 곳의 해안 지역은 리아시스식 해안 형태를 지니고 있어 줌 렌즈를 갖고 가는 것이 좋을 것 같다는 생각을 하고 있습니다. 이번 기회에 괜찮은 줌 렌즈를 하나 구입을 하기 위해 EHLand 쇼핑몰을 검색을 해 보았습니다.

 

EHLand 쇼핑몰에는 다양한 형태의 줌 렌즈들이 있는데 이들 중에 무엇을 사는 것이 좋을지 생각하다보니 어떠한 원리로 만들어져 있는지 궁금해 졌습니다. EHLand의 예릭플 씨한테 물어보면 궁금증이 풀릴 것 같아 이메일을 보냈습니다.

 

 

안녕하세요, 예릭플 씨.

지난 번에 EHLand 사의 렌즈 개발 과정에 대해 친절히 소개해 하셔서 감사드립니다. 이번에 남해안에 여행을 가게 되어 줌 렌즈를 하나 구입을 하려고 합니다. '어떤 렌즈를 구입을 할까?' 고민을 하다보니 각 렌즈들이 만들어지는 과정이 궁금해졌습니다.

 

이메일을 보내고 난 다음 날 바로 예릭플 씨의 답변 메일을 받게 되었고 궁금증이 풀리게 되었습니다.

 

 

혁재 아버지, 안녕하세요.

가족끼리 남해에 여행간다고 하니 부럽네요. 혁재가 많이 좋아할 거 같군요.

이번에는 줌 렌즈를 만드는 공정이 궁금하신가 보네요. 줌 렌즈를 만드는 생산 라인은 복사기와 비슷한 원리로 만들어집니다. EHLand의 모든 줌 렌즈는 모두 같은 구조로 되어 있고 들어가는 모듈도 크게 다르지 않습니다. 각 생산 라인마다 견본 줌 렌즈가 있는데 이들은 기본 구조는 동일하게 제작되어 있습니다. 물론, 각 견본 줌 렌즈들은 서로 거리 조절링에 설정되어 있는 최소 거리와 최대 거리나 조리개 조절링에 설정된 최소치와 최대치가 다릅니다. 생산 라인의 기계는 견본 줌 렌즈의 이들 속성을 확인하여 동일하게 설정된 렌즈를 생산하고 있지요.

 

1.3 디자인

 

여기에서는 줌 렌즈와 줌 렌즈 생산 라인 두 개의 형식으로 구성된 예를 들고자 합니다. 줌 렌즈는 자신을 복제할 수 있는 메소드를 제공하고 있어야 합니다. 클래스 이름은 ZoomLens라 정합시다. 줌 렌즈 생산 라인은 견본 줌 렌즈를 하나 갖고 있게 할 것입니다. 그리고, 제품 생산요청이 들어오면 견본을 복제한 줌 렌즈를 반환하면 될 것입니다. 줌 렌즈 생산 라인에 대한 클래스 이름은 ProLine이라 하겠습니다.

 

이번에는 정상적으로 작성되었는지를 확인하기 위한 클래스나 코드에 대해서는 논하지 않겠습니다. 여러분이 창의적으로 생각을 하셔서 작성해 보세요.

 

[그림 1] 원형 패턴 설계 예

 

1. 4 구현

 

이제 원형 패턴에 대한 예제 프로그램을 구현해 봅시다. 구현 순서는 줌 렌즈, 줌 렌즈 생산 라인 순으로 구현 하겠습니다.

 

2.4.1 줌 렌즈

 

여기에서는 다양한 줌 렌즈를 일반화 관계로 사용하지 않고 하나의 ZoomLens 클래스에서 속성만 다르게 주어 이를 기반으로 개체를 복사하여 사용하기로 하였습니다. 이에 줌 렌즈의 생성자 메서드에서는 최소 줌 레벨과 최대 줌 레벨, 최소 초점 거리, 최대 초점 거리를 입력 인자로 전달받아 생성하도록 하겠습니다. 그리고, 복제를 하기 위한 메서드가 필요할 것입니다. 자신을 복제한 개체를 반환하는 메서드 이름은 Clone이라고 정하겠습니다. 이 외에 줌 인, 줌 아웃, 초점을 가까운 곳으로 이동, 먼 곳으로 이동시키는 기능 및 피사체를 사진을로 변환하는 기능을 추가하도록 하겠습니다.

 

 

namespace AboutPrototypePattern
{
    class ZoomLens
    {
        public enum TypeZoomLens
        {
            NM_NM,
            NM_NF,
            NF_NF,
            MF_NF,
            MF_MF
        }

        readonly int minZoomLevel;
        readonly int maxZoomLevel;
        readonly int minFocus;
        readonly int maxFocus;
        int zoomLevel;
        int focus;

        public ZoomLens(int _minZoomLevel, int _maxZoomLevel, int _minFocus, int _maxFocus)
        {
            this.minZoomLevel = _minZoomLevel;
            this.maxZoomLevel = _maxZoomLevel;
            this.minFocus = _minFocus;
            this.maxFocus = _maxFocus;
        }

        public void Take()
        {
            Console.WriteLine("zoomLevel : {0}, focus : {1}", zoomLevel, focus);
        }

        public int ZoomIn()
        {
            if (zoomLevel < maxZoomLevel)
            {
                zoomLevel++;
            }
            return zoomLevel;
        }

        public int ZoomOut()
        {
            if (zoomLevel < minZoomLevel)
            {
                zoomLevel--;
            }
            return zoomLevel;
        }

        public int NearFocus()
        {
            if (focus > minFocus)
            {
                focus--;
            }
            return focus;
        }

        public int FacFocus()
        {
            if (focus > maxFocus)
            {
                focus++;
            }
            return focus;
        }

        public ZoomLens Clone()
        {
            return new ZoomLens(this.minZoomLevel, this.maxZoomLevel, this.minFocus, this.maxFocus);
        }
    }

 

 

 

2.4.2 줌 렌즈 생산 라인

 

생산 라인은 하나의 줌 렌즈를 견본으로 갖고 있고 이를 기반으로 복사된 렌즈를 생산하기로 하였습니다. 이를 위해 생산 라인의 생성자는 어떠한 견본 렌즈를 갖고 있을 것인지를 입력 인자로 전달받기로 하겠습니다. 그리고, 생산 요청을 받아 견본 렌즈와 동일한 속성 값을 갖는 복제된 제품을 반환하는 메서드를 만들기로 합시다. 메서드 이름은 MakeLens라 하겠습니다.

namespace AboutPrototypePattern
{
    class ProLine
    {
        ZoomLens prototype;
        

        public ProLine(AboutPrototypePattern.ZoomLens.TypeZoomLens typeZoomLens)
        {
            switch (typeZoomLens)
            {
                case ZoomLens.TypeZoomLens.NM_NM: prototype = new ZoomLens(20, 70, 1, 100); break;
                case ZoomLens.TypeZoomLens.NM_NF: prototype = new ZoomLens(20, 70, 1, 200); break;
                case ZoomLens.TypeZoomLens.NF_NF: prototype = new ZoomLens(20, 300, 1, 200); break;
                case ZoomLens.TypeZoomLens.MF_NF: prototype = new ZoomLens(70, 300, 1, 200); break;
                case ZoomLens.TypeZoomLens.MF_MF: prototype = new ZoomLens(70, 300, 10, 200); break;
            }
        }

        public ZoomLens MakeLens()
        {
            ZoomLens product = prototype.Clone();
            return product;
        }
    }
}


 

아래의 글은 언제나 휴일 출판사의 장문석님의 "Escort GoF의 디자인 패턴" 도서의 내용을 정리한 것 입니다. (http://cafe.daum.net/ehclub.net/S8l6/11)

 

빌더 패턴(Builder Pattern)

 

1.1 개요

 

프로그래밍을 하다 보면 개체의 형식 변환을 해야 하는 경우가 발생합니다. 경우에 따라서는 소유 개체에서 피 소유 개체를 목적에 따라 변환 알고리즘을 다르게 적용하여 형식 변환을 해야 되는 경우가 있습니다. 이러한 경우에 빌더 패턴을 사용하던 소유 개체에 대한 클래스와 알고리즘에 대한 클래스를 분리하여 정의할 수 있습니다. 'GoF의 디자인 패턴'에서는 소유 개체를 디렉터라 부르고 알고리즘이 구현된 개체를 빌더라 부르고 있습니다.

 

빌더 패턴에서 빌더는 추상 클래스로 표현하여 개체를 생성하는 메서드에 대한 약속을 합니다. 파생 클래스에서는 약속된 메서드를 목적에 맞는 알고리즘을 사용하여 구체적으로 구현을 해야합니다.

소유 개체를 구현함에 있어 피 소유 개체를 생성하는 알고리즘이 다양할 경우 빌더 패턴을 사용하면 효과적입니다. 차후에 다른 형태의 알고리즘을 적용하여 피 소유 개체를 생성해야 하는 경우에 빌더 클래스에서 파생된 구체화 된 클래스만 추가하면 될 것입니다.

 

1.2 시나리오

 

우리 가족은 매주 토요일에는 여행을 다녀옵니다. 여러분들도 아시다시피 우리 가족은 사진을 찍는 것을 좋아합니다. 이러한 생활을 하다보니 사랑하는 아들 혁재는 자연스럽게 카메라와 사진에 대해 많은 호기심이 생기나 봅니다.

 

"아빠, 어떻게 해서 카메라로 사진을 찍을 수 있는거야?"

 

아들에게 렌즈에 대한 얘기와, 초점 빛에 대한 얘기를 하다보니 지겨운지 자기 방으로 들어가더군요. 이제껏 대부분의 아들의 호기심을 해소시켰다고 자부했었는데 내가 좋아하는 카메라에 대해 설명을 못해 안타까웠어요. 밤 새 고민을 하다 근처에 있는 EHCamera 회사를 견학하면 좋겠다는 생각을 하게 되었고 견학에 필요한 것이 무엇인지 확인하고 견학 신청을 하였습니다.

 

몇 일 뒤에 우리 가족은 EHCamera 회사를 방문했어요. 회사 입구에서부터 안내원이 반갑게 맞아주었고 회사에 대한 간단한 소개와 생산 라인을 견학할 수 있었어요. 그리고, 엔지니어와의 만남의 시간이 주어졌는데 그가 건네준 명함에는 '이 매핑'이라는 이름이 적혀있더군요.

 

"매핑님, 카메라에 상이 맺혀 사진이 되는 과정이 어떻게 되나요?"

"음, 카메라로 사진을 찍을 수 있는 원리는 사람의 눈으로 사물들을 보는 원리와 흡사합니다. 우리가 사물을 볼 수 있는 것은 빛이 사물에 부딪혀 반사되는 것이 눈에 그려지는 것입니다. 쉽게 얘기하면 빛이 그림을 그리는 것이지요."

"아빠, 학교에서 배웠어. 빛은 여러 가지 색을 지니고 있다고 배웠어. 그리고, 실험 시간에 스펙트럼을 통해 빛의 반사에 대해 알게 되었어. 카메라도 사람의 눈과 마찬가지구나."

매핑씨는 혁재가 하는 말을 듣고 좀 더 자세한 얘기를 해주었어요. 조리개를 열어 빛을 얻어오는 것과 반사경을 통해 상이 맺히는 것에 대하여 알게 되었습니다. 그리고, 설정에 따라 얻어온 상을 이미지로 변환하는 원리도 얘기해 줬어요. 그리고, 이 부분은 소프트웨어적으로 처리를 한다고 하더군요.

 

"아빠, 그럼 아빠도 저런 거 만드는 거야?"

"음. 비슷해"

 

그리고, 집에 돌아와서 카메라 효과에 관련된 자료를 조사 했어요. 조명에 의해 적목 현상을 어떻게 개선을 시키는 지도 알게 되었고 피사체가 사람인 경우에는 윤곽선을 부드럽게 해 주는 원리에 대해서도 알게 되었죠. 그리고, 새로운 카메라에 기존의 효과 외에 다른 효과들을 손쉽게 하기 위한 방법을 알게 되었어요. 이는 각각의 효과마다 별도의 모듈을 사용하고 각각의 모듈은 동일한 인자를 입력 받아 그림을 만들어 내는 공통적인 인터페이스를 갖게 하면 됩니다.

 

1.3 디자인

 

이번에는 카메라와 사진, 사진 빌더로 빌더 패턴에 대한 예를 들려고 합니다. 카메라는 사진을 찍는 기능이 있고 효과를 줄 수 있게 하려고 합니다. 대신 효과를 주는 부분을 사진 빌더를 통해 수행하게 할 것입니다.

 

카메라는 디렉터 역할을 하며 Camera 이름의 클래스로 구현을 하겠습니다.

 

사진은 카메라를 통해 사용자가 얻고자 하는 개체로 Picture라고 정하겠습니다.

 

사진 빌더는 추상클래스로 PictureBuilder라 하겠습니다. 사진 빌더에서 파생된 클래스는 피사체의 날카로운 부분을 매끈하게 바꾸어 사진을 생성하는 SmoothBuilder가 있습니다. 그리고, 피사체의 적목 현상이 발생하는 것을 보정하여 사진을 생성하는 REPeventBuilder도 추가하겠습니다.

[그림 1] 빌더 패턴 설계 예

 

1. 4 구현

 

이제 빌더 패턴에 대한 예제 프로그램을 구현해 봅시다. 구현 순서는 사진, 사진 빌더, 카메라 순으로 하겠습니다.

 

2.4.1 사진

 

사진은 사진의 이름을 가지고 있는 클래스로 생성합니다.

namespace AboutBuilderPattern

{

class Pictrure

{

string Name;

public Pictrure(string _name)

{

this.Name = _name;

}

public override string ToString()

{

return this.Name;

}

}

}

 

2.4.2 사진 빌더

 

사진 빌더는 피사체를 입력 매개변수로 받아 특정 효과를 거쳐 사진을 생성하는 역할을 수행합니다. 추상 클래스 PictureBuilder에서는 이에 대한 약속을 해야합니다. 효과를 주어 사진을 생성하는 기능을 Effect라 하겠습니다. 그리고, 입력 인자로 전달 받을 피사체의 형식을 string 형식을 사용하겠습니다.

 

namespace AboutBuilderPattern

{

abstract class PictureBuilder

{

public abstract Pictrure Effect(string orgin);

}

}

 

PictureBuilder로 부터 파생된 클래스 SmoothBuilder에서는 기반 클래스에서 약속한 Effect 메서드를 구현해야 합니다. 그리고, Effect 메서드에서는 날카로운 부분을 찾는 과정과 매끈하게 보정하는 작업이 필요할 것 입니다. 이들 기능에 대한 이름은 FindSharp, SharpToSmooth라고 정하겠습니다.

 

namespace AboutBuilderPattern

{

class SmoothBuilder:PictureBuilder

{

const string SMOOTH = "Smooth";

const string SHARP = "Sharp";

 

int FindSharp(string origin)

{

return origin.IndexOf(SHARP);

}

Pictrure SharpToSmooth(string origin, int index)

{

int flen = SHARP.Length;

string front = origin.Substring(0, index);

string last = origin.Substring(index + flen, origin.Length - index - flen);

return new Pictrure(front + SMOOTH + last);

}

 

public override Pictrure Effect(string orgin)

{

int index = FindSharp(orgin);

return SharpToSmooth(orgin,index);

}

}

}

 

PictureBuilder에서 파생된 또 다른 클래스 REPreventBuilder에서도 Effect 메서드를 구현해야 할 것입니다. 그리고, Effect 메서드에서는 적목 현상이 있는 눈의 위치를 보정하는 작업이 필요합니다. 이들 기능에 대한 이름은 FindRedEye, RedEyeToNormalEye라고 정하겠습니다.

 

namespace AboutBuilderPattern

{

class REPreventBuilder:PictureBuilder

{

const string RED_EYE = "RedEye";

const string NORMAL_EYE = "NormalEye";

 

public override Pictrure Effect(string orgin)

{

int index = FindRedEye(orgin);

return RedEyeToNormalEye(orgin, index);

}

 

int FindRedEye(string orgin)

{

return orgin.IndexOf(RED_EYE);

}

Pictrure RedEyeToNormalEye(string origin, int index)

{

int flen = RED_EYE.Length;

string front = origin.Substring(0, index);

string last = origin.Substring(index + flen, origin.Length - index - flen);

return new Pictrure(front + NORMAL_EYE + last);

}

}

}

 

2.4.3 카메라

 

카메라에는 셔터를 누르면 피사체를 사진으로 만들어주는 기능이 있어야 할 것입니다. 이러한 기능을 Effect Normal이라고 하겠습니다. 그리고, 찍은 사진을 필요할 때 얻어오는 기능도 있으면 사용자는 편리할 것입니다. 이러한 기능은 GetPicture 라고 합시다. 이 외에도 카메라에 줄 수 있는 효과들에 대한 열거형을 정의하여 사용을 한다면 좀 더 효과적으로 사용 할 수 있을 것입니다.

 

namespace AboutBuilderPattern

{

enum EffectType

{

EF_PREVENTRE=0,

EF_SMOOTH=1,

EF_NORMAL = 2,

EF_SMOOTH_PRERE=3

}

 

 

class Camera

{

PictureBuilder []pbs;

Pictrure picture;

 

public Camera()

{

pbs = new PictureBuilder[2];

pbs[0] = new REPreventBuilder();

pbs[1] = new SmoothBuilder();

picture = new Pictrure(string.Empty);

}

 

public Pictrure PressAShutter(string origin, EffectType effect)

{

switch (effect)

{

case EffectType.EF_NORMAL: EffectNormal(origin); break;

case EffectType.EF_PREVENTRE: PreventRedEye(origin); break;

case EffectType.EF_SMOOTH: Smoothing(origin); break;

case EffectType.EF_SMOOTH_PRERE: SmoothPrere(origin); break;

}

return GetPicture();

}

 

public Pictrure GetPicture()

{

return picture;

}

 

private void SmoothPrere(string origin)

{

Smoothing(origin);

PreventRedEye(origin);

}

 

private void Smoothing(string origin)

{

this.picture = pbs[(int)EffectType.EF_SMOOTH].Effect(origin);

}

 

private void PreventRedEye(string origin)

{

this.picture = pbs[(int)EffectType.EF_PREVENTRE].Effect(origin);

}

 

private void EffectNormal(string origin)

{

this.picture = new Pictrure(origin);

}

}

}

 

그리고, 정상적으로 구현된 것을 확인하기 위한 코드는 진입점인 main에 구현하기로 하겠습니다. 테스트는 카메라에 적목 현상이 있는 눈과 날카로운 몸체를 피사체로 전달하여 사진을 얻어오는 것으로 하겠습니다. 물론, 여러 효과를 주어 결과 사진을 확인 해야겠습니다.

 

namespace AboutBuilderPattern

{

class Program

{

static void Main(string[] args)

{

Camera camera = new Camera();

camera.PressAShutter("RedEyeSharpBody", EffectType.EF_NORMAL);

Console.WriteLine(camera.GetPicture());

 

camera.PressAShutter("RedEyeSharpBody", EffectType.EF_PREVENTRE);

Console.WriteLine(camera.GetPicture());

 

camera.PressAShutter("RedEyeSharpBody", EffectType.EF_SMOOTH);

Console.WriteLine(camera.GetPicture());

 

camera.PressAShutter("RedEyeSharpBody", EffectType.EF_SMOOTH_PRERE);

Console.WriteLine(camera.GetPicture());

}

}

}

 

 

[그림 2] 빌더 패턴 예제 실행 화면

 

 

AboutBuilderPattern.zip

자신이 개발한 닷넷 프로그램을 배포 할 때, 디컴파일러 프로그램(예: Reflector )으로 인해 소스가 노출 될 수 있습니다.

난독화 기능의 프로그램을 이용해서 네임스페이스, 클래스, 속성, 메서드, 지역 변수 등등 네이밍이 되어 있는 것들의 이름을

난해하게 변경해주면 디컴파일러로 소스를 본다고 하여도 어떠한 기능을 하는지 알 수 없게 만들 수 있습니다.

 

[이미지 1] 난독화 하기 전 후 모습

 

 

 

Visual Studio 2008 Visual Studio Tools 폴더에 설치되는 Dotfuscator Community Edition 프로그램을 이용하여

난독화를 하는 과정에 대해 설명하겠습니다.

 

 

[이미지 2] 프로그램 실행시 뜨는 창

 

Dotfuscator Community Edition 프로그램을 실행시키면 위의 창의 뜨게 됩니다.

"아니요, 등록하지 않습니다." 버튼을 클릭합니다.

 

 

 

[이미지 3] 프로젝트 형식선택

 

"새 프로젝트 만들기"를 선택하신 후 확인을 누릅니다.

 

 

 

[이미지 4] 어셈블리를 목록에 추가

 

입력 탭이 Default로 선택되어 있습니다. "빨간색 부분의 어셈블리를 찾아서 목록에 추가" 버튼을 클릭합니다.

입력 어셈블리 추가 창이 뜨면 찾아보기 버튼을 눌러 난독화할 어셈블리를 지정하고 확인 버튼을 클릭합니다.

 

 

 

[이미지 5] 어셈블리 선택

 

저는 제가 만든 실행 파일과 함께 필요한 dll들을 선택하였습니다.

 

 

 

[이미지 6] 추가된 모습

 

어셈블리들이 추가된 모습을 확인 하실 수 있습니다.

 

 

 

[이미지 7] 제외할 특정 항목 선택하기

 

이름 바꾸기 탭을 클릭하시면 제외 탭에 제외할 특정 항목을 선택 하실 수 있습니다.

실제 ChartFX를 디컴파일러로 소스를 확인 할 경우, 사용자에게 제공되는 부분은 그대로 노출하되 core들은 a1, a2, 32 등등 난해하게 되어 있습니다.

자신이 만든 라이브러리를 개발자에게 공개할 때, core들은 감추고 싶을 때, 이 기능을 사용하면 유용할 것입니다.

 

 

[이미지 8] 빌드 완료

 

빌드 탭으로 이동 후 "빌드" 버튼을 클릭한 후 Dotfuscator 프로젝트를 저장해줍니다.

지정한 곳에 난독화된 어셈블리파일이 생성됩니다.

위의 이미지 처럼 이름을 바꾼 개수와 이름을 바꾼 비율 확인 하실 수 있습니다.

 

 

 

[이미지 9] 빌드한 후의 내부 코드

 

변경한 어셈블리들의 내부 코드입니다. 네임스페이스명은 사라지고 클래스명들은 a,b,g,h 등 난해하게 변경 되었습니다.

난독한 프로그램 실행시 아무 문제 없이 잘 실행 되는 것을 확인 하실 수 있습니다.

아래의 글은 언제나 휴일 출판사의 장문석님의 "Escort GoF의 디자인패턴" 도서의 내용을 정리한 것 입니다. (http://cafe.daum.net/ehclub.net/S8l6/11)

 

추상 팩토리 패턴(Abstract Factory Pattern)

 

1.1 개요

 

프로그래밍을 하다 보면 특정 목적에 따라 사용해야 하는 개체들이 서로 호환성이 있어야 하는 경우가 발생합니다. 목적에 따라 사용해야 하는 개체군이 다른 경우에 특정 목적에 맞게 호환성 있는 개체가 무엇인지를 조사하고 주의 깊게 사용하는 비용이 발생할 수 있습니다. 이러한 경우에 추상 팩토리 패턴을 사용하면 효과적으로 비용을 줄일 수 있을 것 입니다.

 

추상 팩토리 패턴에서는 서로 호환성 있는 개체들을 생성하는 부분만 담당하는 개체를 제공하는 것입니다. 이와 같은 개체를 팩토리 개체라 부릅니다. 그리고, 구체화 된 팩토리 개체에서 약속된 개체들을 생성하는 인터페이스에 대한 추상화 된 형식을 제공을 합니다. 이와 같은 형태로 설계하면 사용자는 특정 목적에 맞게 호환성 있는 개체가 무엇인지를 조사하는 비용을 줄일 수 있습니다. 또한, 목적이 바뀌어도 구체화 된 팩토리 개체만 교체하면 되기 때문에 유지 보수 비용을 줄일 수 있게 됩니다.

 

 

1.2 시나리오

 

EHWorld(Every Holiday World)에는 Everyday 카메라와 Holiday 카메라가 있습니다. 두 종류의 카메라 모두 렌즈 교환식 카메라입니다. 저는 사람이나 건물 등을 촬영할 때에는 부드럽게 표현해 주는 Everyday 카메라를 선호합니다. 그리고, 여행을 가서 아름다운 풍경을 찍을 때에는 자연스럽게 표현해 주는 Holiday 카메라를 선호합니다. 그런데, 저에게 고민이 하나 있습니다. 사진에 취미를 갖고 렌즈를 하나 하나 구입하다 보니 이제는 여행을 갈 때마다 Holiday 카메라와 호환되는 렌즈를 찾는데 너무 많은 시간이 소요됩니다. 물론, 여행을 다녀오고 난 후에 다시 Everyday 카메라와 호환되는 렌즈를 찾을 때도 너무 많은 시간이 소요되네요.

 

어떻게 하면 제 고민을 해결할 수 있을까요?

 

어느 날 저의 아내가 저에게 선물을 가지고 왔습니다. 두 개의 라면 박스였습니다. 저는 순간 짜증이 밀려왔지만 아내의 말을 듣고 나니 짜증은 고마움과 기쁨으로 전이되었습니다.

 

"E 라면 박스에는 Everyday 렌즈들을 넣고 H라면 박스에는 Holiday 렌즈들을 넣으면 좋지 않을까?"

 

예전보다 렌즈를 찾는데 드는 비용은 줄어들었습니다. 하지만, 여전히 많은 시간을 소요해야 원하는 렌즈를 찾을 수 있었습니다. 강 건너 풍경을 찍을 때에는 줌 렌즈를 사용을 해야 원하는 피사체를 효과적으로 표현할 수 있구요. 사랑하는 이들을 찍을 때에는 35mm 단 렌즈를 선호하고 영원한 동반자인 사랑하는 나의 아내를 찍을 때에는 45mm 단 렌즈를 선호합니다. 그리고, 제가 강의했던 학생들이 교육 과정을 마치고 나면 수료식을 수행을 합니다. 이 때는 70mm 단 렌즈를 사용하곤 합니다. 가끔 아들이나 아내가 저의 카메라와 렌즈를 사용할 일이 있게 되면 어떠한 렌즈를 사용하는 것이 좋은지를 몰라서 대충 골라가곤 합니다. 그리고는 촬영된 사진이 이상하다고 투덜대곤 합니다.

 

어떻게 하면 우리 가족의 고민을 해결할 수 있을까요?

 

이 문제를 해결하기 위해 라면 박스 안에 칸막이를 만들었습니다. 3 X 3 형태로 만들어 우측부터 단 렌즈, 표준 렌즈, 줌 렌즈를 배치하였습니다. 그리고, 앞에는 가까운 피사체를 찍을 수 있는 렌즈를 배치하고 맨 뒤에는 먼 곳에 있는 피사체를 찍을 수 있는 렌즈를 배치하였습니다. 그리고, 박스 앞에 각각의 카메라를 배치할 수 있는 공간을 별도로 만들었습니다.

 

그 후로 우리 가족은 렌즈를 찾는 비용을 줄일 수 있게 되었고 아내와 아들도 자신들이 찍은 사진에 만족해합니다. 그런데, 이제 아내와 아들이 저와 같이 여행을 가면 서로 자신이 사진을 찍어야 한다고 실랑이를 벌이는 행복한 고민에 빠졌습니다.

 

1.3 디자인

 

여기에서는 렌즈의 종류는 각 기종 별로 하나의 렌즈만 제공하는 수준으로 디자인하려고 합니다. 여기에서 보여드리고자 하는 프로그램에는 카메라, 렌즈, 특정 기종의 카메라와 렌즈를 생성하는 역할을 하는 팩토리, 테스터로 분류를 할 것입니다.

 

카메라와 렌즈, 팩토리는 Everyday에 관련된 것과 Holiday에 관련된 구체화 클래스와 일반화 된 추상 클래스 구조로 만들어야겠지요. 여기에서 Everyday에 관련된 것들은 접두사 Ev를 사용하고 Holiday에 관련된 것들은 접두사 Ho를 사용할 것입니다.

 

카메라에는 렌즈를 장차하고 탈착하는 기능과 사진을 찍는 기능에 대해 구현 약속을 합시다. 렌즈에는 상을 얻어오는 기능에 대한 구현 약속을 하겠습니다. Ev 렌즈의 경우 손 쉽게 초점을 맞출 수 있는 기능을 제공하고 있어서 Ev카메라로 셔터를 누르면 자동으로 초점을 맞춘 후에 사진을 찍을 수 있을 것입니다. Ho렌즈의 경우에는 사용자에 의해 초점을 맞출 수 있는 기능을 제공합시다. Ho카메라의 경우에는 초점을 맞추고 사진을 찍는 것으로 구현을 해 봅시다.

 

테스터에서는 EvDayFactory 개체와 HoDayFactory 개체를 통해 각각의 카메라와 렌즈 개체를 생성을 하고 교차로 사용했을 때 호환성이 위배되는 지에 대한 테스트를 수행을 합니다. 그리고, Ev 카메라에 Ev 렌즈를 장착하여 사진을 찍고 Ho카메라와 Ho렌즈를 장착하여 사진을 찍는 테스트를 해 봅시다.

 

 

[그림 1] 추상 팩토리 패턴 설계 예

 

1. 4 구현

 

이제 구체적으로 구현을 해 보기로 합시다.

 

먼저, 카메라와 렌즈에 대한 구현을 하겠습니다. 그리고, 팩토리 부분을 구현을 합시다. 마지막으로 테스터를 구현을 하려고 합니다.

 

1.4.1 렌즈

 

렌즈의 경우는 추상 클래스인 Lens와 이를 기반으로 파생된 EvLens, HoLens가 있습니다. 그리고, 추상 클래스인 Lens에는 상을 맺히는 기능에 대해 Take 이름의 메서드로 구현 약속하겠습니다.

 

namespace AboutFactoryPattern

{

abstract class Lens

{

public abstract void Take();

}

}

 

EvLens의 경우 Lens를 기반의 파생 클래스로 만들기로 하였기 때문에 기반 클래스 Lens에서 약속한 Take 메서드를 구현하여야 합니다. 그리고, EvLens에는 자동 초점을 맞춰주는 기능을 별도로 제공하겠습니다. 자동 초점을 맞춰주는 기능에 대한 명칭은 AutoFocus라 정하겠습니다.

namespace AboutFactoryPattern

{

class EvLens:Lens

{

public override void Take()

{

Console.WriteLine("부드럽다.");

}

public void AutoFocus()

{

Console.WriteLine("AutoFocus.....");

}

}

}

 

HoLens도 Lens를 구체화 시킨 클래스 형태로 만들게 디자인 되어 있습니다. 이를 위해서는 Take 메서드를 구현하여야 할 것 입니다. 그리고, HoLens에는 사용자에 의해 초점을 맞추는 기능을 제공하기로 했었습니다. 해당 기능에 대한 명칭은 ManualFocus라 정하겠습니다.

 

namespace AboutFactoryPattern

{

class HoLens : Lens

{

public override void Take()

{

Console.WriteLine("자연스럽다.");

}

public void ManualFocus()

{

Console.WriteLine("사용자의 명령대로 초점을 잡다.");

}

}

}

 

1.4.2 카메라

 

카메라의 경우는 추상 클래스인 Camera와 파생 클래스 EvCamera, HoCamera가 있습니다. 그리고, 추상 클래스인 Camera에는 사진을 찍는 메서드를 제공합시다. 이에 대한 부분은 공통적으로 렌즈를 통해 상을 맺히는 부분이 있지만 세부적인 사항은 카메라의 종류에 따라 다를 수 있으므로 가상 메서드로 구현을 하겠습니다. 그리고 렌즈를 장착하는 기능과 탈착하는 기능이 필요할 것입니다. 렌즈를 장착하는 기능은 카메라에 따라 상이하기 때문에 추상 메서드로 만들겠습니다. 렌즈를 탈착하는 기능은 카메라에 상관이 없을 것 같습니니다.

 

메서드

기능

virtual bool TakeAPicture();

사진 찍다.

virtual bool PutInLens(Lens lens);

렌즈를 장착하다.

Lens GetOutLens();

렌즈를 탈착하다.

 

그리고, 카메라에는 장착한 렌즈를 위한 멤버 변수(멤버 필드라고도 함)가 필요할 것입니다. 이 외에 파생 클래스 개체에서 접근을 위해 렌즈를 설정하는 멤버 메서드와 설정된 렌즈를 얻어오는 멤버 메서드를 추가하겠습니다. 가급적 멤버 변수는 노출 수준을 private로 지정하여 정보 은닉하시기 바랍니다. 잘못된 값이 왔을 때에 대한 필터링 작업을 한 곳에서 수행을 함으로써 전체 유지 보수 비용을 줄일 수 있습니다. 여기에서도 장착된 렌즈를 관리하는 멤버 변수를 private로 지정을 할 것입니다. 파생 클래스 개체에서 이에 대한 접근이 가능하게 하기 위한 도구로 노출 수준이 protected로 지정된 멤버 메서드를 제공한다는 것은 이미 알고 있을 것이라 생각합니다.

 

 

namespace AboutFactoryPattern

{

abstract class Camera

{

Lens lens;

 

protected Camera()

{

lens = null;

}

 

public abstract bool PutInLens(Lens lens);

 

 

public virtual bool TakeAPicture()

{

if (lens == null)

{

return false;

}

lens.Take();

return true;

}

 

public Lens GetOutLens()

{

Lens re = lens;

lens = null;

return re;

}

 

protected void SetLens(Lens _lens)

{

this.lens = _lens;

}

 

protected Lens GetLens()

{

return this.lens;

}

 

}

}

 

EvCamera는 기반 클래스 Camera에서 파생된 클래스입니다. 기반 클래스 Camera에 구현 약속된 메서드인 PutInLens를 구현 해야합니다. 그리고, 사진을 찍는 TakeAPicture 메서드의 경우도 자동 초점을 하는 부분이 있으므로 재정의 해야 합니다.

 

namespace AboutFactoryPattern

{

class EvCamera:Camera

{

public override bool TakeAPicture()

{

Lens lens = base.GetLens();

EvLens evLens = lens as EvLens;

if (evLens == null)

{

return false;

}

 

evLens.AutoFocus();

return base.TakeAPicture();

}

 

public override bool PutInLens(Lens lens)

{

EvLens evLens = lens as EvLens;

if (evLens == null)

{

return false;

}

 

base.SetLens(lens);

return true;

}

}

}

 

 

HoCamera의 경우도 EvCamera와 동일한 이유로 TakeAPicture 메서드와 PutInLens를 구현하여야 합니다.

 

namespace AboutFactoryPattern

{

class HoCamera:Camera

{

public override bool TakeAPicture()

{

Lens lens = base.GetLens();

HoLens hoLens = lens as HoLens;

if (hoLens == null)

{

return false;

}

hoLens.ManualFocus();

return base.TakeAPicture();

}

 

public override bool PutInLens(Lens lens)

{

HoLens hoLens = lens as HoLens;

if (hoLens == null)

{

return false;

}

 

base.SetLens(hoLens);

return true;

}

}

}

 

 

1.4.4 팩토리

 

팩토리의 경우는 추상 클래스인 DayFactory와 파생 클래스 EvDayFactory, HoDayFactory가 있습니다. 그리고, 추상 클래스인 DayFactory에는 카메라를 생성하는 메서드와 렌즈를 생성하는 메서드를 구현 약속하였습니다.

 

 

namespace AboutFactoryPattern

{

abstract class DayFactory

{

List<Camera> cameras;

List<Lens> lenses;

 

public abstract Camera CreateCamera();

public abstract Lens CreateLens();

 

protected DayFactory()

{

cameras = new List<Camera>();

lenses = new List<Lens>();

}

 

protected void PutCamera(Camera camera)

{

this.cameras.Add(camera);

}

protected void PutLens(Lens lens)

{

this.lenses.Add(lens);

}

}

}

 

 

EvDayFactory와 HoDayFactory에서는 구현 약속되어 있는 두 개의 메서드를 구현해야 할 것입니다.

namespace AboutFactoryPattern

{

class EvDayFactory:DayFactory

{

 

public override Camera CreateCamera()

{

return new EvCamera();

}

 

public override Lens CreateLens()

{

return new EvLens();

}

}

}

 

namespace AboutFactoryPattern

{

class HoDayFactory:DayFactory

{

public override Camera CreateCamera()

{

return new HoCamera();

}

 

public override Lens CreateLens()

{

return new HoLens();

}

}

}

 

1.4.5 테스터

 

테스터는 팩토리를 통해 생성된 카메라와 렌즈를 이용하는 클라이언트 클래스입니다. 여기에서는 Tester라고 정하겠습니다.

 

테스터의 생성자에서는 EvDayFactory 개체와 HoDayFactory 개체를 생성하겠습니다. 그리고, 이들을 통해 카메라와 렌즈를 생성하는 작업을 수행하기로 하겠습니다.

그리고, Test메서드를 정의하기로 하겠습니다. 여기에서는 호환성을 테스트하는 작업을 수행하기로 하겠습니다.

 

namespace AboutFactoryPattern

{

class Tester

{

DayFactory []factories;

Camera []cameras;

Lens []lenses;

 

public Tester()

{

Init();

}

 

private void Init()

{

this.factories = new DayFactory[2];

this.cameras = new Camera[2];

this.lenses = new Lens[2];

 

this.factories[0] = new EvDayFactory();

this.factories[1] = new HoDayFactory();

 

MakeCameraSet(0);

MakeCameraSet(1);

}

 

private void MakeCameraSet(int index)

{

DayFactory factory = factories[index];

this.cameras[index] = factory.CreateCamera();

this.lenses[index] = factory.CreateLens();

}

public void Test()

{

Test(this.cameras[0], this.lenses[1]);

Test(this.cameras[0], this.lenses[0]);

Test(this.cameras[1], this.lenses[1]);

}

 

private void Test(Camera camera, Lens lens)

{

Console.WriteLine("테스트");

if (camera.PutInLens(lens) == false)

{

Console.WriteLine("카메라가 렌즈에 장착이 되지 않았음");

}

if (camera.TakeAPicture() == false)

{

Console.WriteLine("사진이 찍히지 않았습니다");

}

camera.GetOutLens();

}

}

}

 

 

namespace AboutFactoryPattern

{

class Program

{

static void Main(string[] args)

{

Tester tester = new Tester();

tester.Test();

}

}

}

 

 

[그림 2] 추상 팩토리 패턴 예제 실행 화면

 

 

 

AboutAbstractFactoryPattern.zip

'.Net > 디자인패턴' 카테고리의 다른 글

C# Strategy Pattern  (0) 2013.10.22
Escort GoF의 디자인 패턴- Prototype Pattern  (0) 2012.07.06
Escort GoF의 디자인 패턴- Builder Pattern  (0) 2012.07.06
  1 Image helpImage = RWAS.Properties.Resources.help;
  2 Bitmap helpBitmap = new Bitmap(helpImage);
  3 formHelp.Icon = Icon.FromHandle(helpBitmap.GetHicon());

 

'.Net > C#' 카테고리의 다른 글

C# Serialize, Deserialize  (0) 2012.08.21
C# DoubleBuffering (더블 버퍼링)  (0) 2012.08.07
C# UserControl->UserControl 네이버 지식인 답변  (0) 2012.07.17
C# Thread Test Project  (0) 2012.07.11
C# Resources에서 이미지 가져오기  (0) 2012.07.09

▌ 도서관리 프로그램
1. 문제 정의
    도서관에서 도서 대여 상황을 관리하는 프로그램을 작성한다. 도서관리는 도서 입력, 삭제, 검색, 대여, 반
   납의 기능을 핵심으로 한다.
2. 요구사항
    (1) 자료구조 조건: 도서정보 저장을 위한 2차원 정수 배열 (최대도서수: 100권)
    (2) 도서 정보
        A. 도서번호 (예: 000001)
        B. 도서대금: (예: 12000)
        C. 대여자정보: 도서를 빌려간 학생의 학번 (예: 201220123)
        D. 대여날짜: 도서를 빌려간 날짜 (예: 20120509 = 2012년 5월 9일)
    (3) 함수설계 조건: 메인함수를 제외하고 최소 5개의 함수 설계; 즉 도서 입력, 삭제, 검색, 대여, 반납
    의 주요 기능 별로 독립된 함수가 설계가 되어야 함
    (4) 메뉴기반 구조 설계
3. 핵심기능
    (1) 도서 입력
        도서번호, 도서대금을 입력으로 받아서 도서정보 자료구조에 저장
    (2) 도서 삭제
        도서 번호를 입력으로 도서정보 자료구조 내의 해당 도서에 관한 정보를 지움; (자료구조 내에 도
        서 삭제로 인한 빈 공간이 생기지 않도록 자료구조 정리 필요)
        = 오류처리: 삭제할 도서가 실제로 없는 경우, 대여자가 있는 경우,, 기타.
    (3) 도서 검색
        검색조건 – 1) 도서번호, 2) 대여자정보로 검색
        대여자정보검색의 경우, 대여자가 여러권의 책을 빌렸을 경우, 해당 도서들을 모두 출력
    (4) 도서 대여
        도서 번호, 대여날짜와 대여자정보(학번)을 입력받아서 도서 대여 처리
        = 오류처리: 대여할 도서가 실제로 없는 경우, 대여자가 이미 있는 경우,, 기타.
    (5) 도서 반납
        도서 번호, 대여자정보(학번), 반납 날짜를 입력 받아서 연체금 계산하여 출력
        도서연체금계산규칙
            1.최초 10일 무료
            2.연체기간 15일 미만 – 도서 대금의 2.5%
            3.연체기간 15일 이상 30일 미만 – 도서 대금의 5%
            4.연체기간 30일 이상 – 도서 대금의 8%
            = 오류처리: 반납할 도서가 실제로 없는 경우, 대여자정보가 맞지않는 경우,, 기타.

4. 오류처리
    각 기능 마다 제시한 오류처리이외 중요하다고 생각되는 예외 상황에 대한 처리 수행 (보고서에 명시)
5. 입 / 출력 형식
    핵심 기능들을 메뉴 선택 방식으로 수행.
    종료 메뉴에 의해서만 프로그램이 종료되는 반복메뉴기반으로 자율 형식으로 작성.

 

 

 

 

 

개판 소스임... 

ManageBooks.zip

 

'기타 > C' 카테고리의 다른 글

timeSetEvent  (0) 2012.08.20
C언어 작업관리자 구현중  (0) 2012.08.19
C언어 장강사님의 라이브러리  (0) 2010.10.05

다중 복사 프로그램입니다.
 닷넷프레임워크2.0 기반입니다~~
실행 오류 나시는분은 닷넷프레임워크2.0 설치해주세요~

 

 

 



다중 복사 프로그램 v.1.0.0.1

 

MultiCopy_Setup_v1.0.0.1.exe

 

프로그램 기능

1. F1,F2,F3,F4를 이용해 복사

2. F5,F6,F7,F8을 이용해 붙여넣기

3. F12키를 이용해 일시정지

 

주의사항

작업하는 프로그램의 단축키 F1~F8은 동작하지 않음

(단, Shift,Alt,Ctrl 등 조합키에 인한 동작은 가능)

 

 

프로그램 UI

 

 

프로그램 구동시 오른쪽 아래쪽에 트레이 아이콘으로 실행이 됩니다.

프로그램 구동시 시작이 된 상태이며

일시정지를 누르면 F1~F8의 키 입력 제한이 풀립니다.

일시정지의 단축키는 F12입니다.

종료는 프로그램 종료입니다.

 

문의 및 버그사항 댓글 달아 주시면 감사하겠습니다.

후킹 사용해보면서 만든 프로그램이라 부족한게 많을 것 같네요.

텍스트만 복사가능합니다.^^

 

 

 

'프로그램 > 다중복사' 카테고리의 다른 글

다중 복사 프로그램 v1.0.0.2  (2) 2012.08.01

C# Hooking 오픈 소스입니다.

예제 프로젝트도 함께 있습니다.

 

globalhook2_src.zip

 

 

참고:

http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C

 

지정한 폴더 감시하기

 

1. 개요

[그림 1. 프로그램 동작화면]

파일을 공유하는 프로그램을 작성하다 보면, 특정 폴더에 있는 파일 및 폴더의 정보를 실시간으로 리스트에 띄워주어야 하는 경우가 발생할 수 있습니다.

여기에서는 이러한 경우에 필요한 기술 노하우를 전달하려고 합니다.

 

이를 위해 [그림1. 프로그램 동작화면]과 같이 특정 폴더 안에 파일 및 폴더가 생성, 이름변경, 삭제가 발생 하였을 때,

파일 목록 리스트를 갱신하고 Log를 남기는 예를 보여주고자 합니다.

 

2. 얻을 수 있는 기술

-지정한 폴더 감시

-특정 폴더의 파일 정보 얻기

 

3. 사용할 Class 소개하기

FileSystemWatcher : 파일 시스템 변경 알림을 수신하면서 디렉토리 또는 디렉토리의 파일이 변경되면 이벤트를 발생시킵니다.

-네임스페이스 : System.IO

-어셈블리 : System(System.dll)

 

 

    

속성

설명

Path

조사할 폴더의 경로를 가져오거나 설정

NotifyFilter

조사할 변경 내용 형식을 가져오거나 설정

Filter

폴더에서 모니터닝할 파일을 결정하는데 사용되는 필터 문자열을 가져오거나 설정,

특정 파일 감시 ex)*.exe,(모두 감시"", *.*) 

EnableRaisingEvents

구성 요소가 활성화 되는지 여부를 나타내는 값을 가져오거나 설정

 

 

const string FolderName = "Test";

FileSystemWatcher fs = new FileSystemWatcher();//개체 생성 
										

fs.Path = FolderName; //Test 폴더 감시 
										

fs.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName; 

fs.Filter = ""// *.*
										

              

fs.Created += new FileSystemEventHandler(fs_Created); 

fs.Deleted += new FileSystemEventHandler(fs_Deleted); 

fs.Renamed += new RenamedEventHandler(fs_Renamed);               

fs.EnableRaisingEvents = true//이벤트 활성화 
										

 

 

 

DirectoryInfo : 디렉토리 및 하위 디렉토리를 만들고, 이동하고, 열거하는 인스턴스 메서드를 노출합니다.

-네임스페이스 : System.IO

-어셈블리 : mscorlib(mscorlib.dll)

const string FolderName = "Test";

DirectoryInfo dti = new DirectoryInfo(FolderName); //개체 생성
										

FileInfo[] files = dti.GetFiles();   //해당 폴더의 파일정보 얻기

 

 

4. 프로그래밍 UI 디자인

단계1. 프로젝트 생성

[그림 2. 프로젝트 생성]

    

    단계2. Form UI 디자인하기

    

[ 그림 3. Form UI 디자인하기]

5. 프로그래밍하기

5.1 프로그래밍에 앞서 고민하기

이 프로그램에서 처리할 이벤트를 생각해 봅시다.

먼저, Form이 Load되는 시점에 이벤트를 등록하여야만 프로그램 동작 중에 감시하는 폴더의 이벤트를 감지 할 수 있겠습니다.

또한 감시하는 폴더에 원래 존재 하였던 파일들의 정보도 얻어와서 리스트 박스에 띄워줘야 하기 때문에 DictionaryInfo 클래스를 이용해

감시하는 폴더의 파일들의 정보를 얻어와서 listBox_filelist에 아이템을 추가해줍니다.

프로그램 초기화는 끝났고, 이제 프로그램 동작 시점에 대해 설명해드리겠습니다.

FileSystemWatcher 개체에서 파일이 생성 되었다면, listBox_filelist에 아이템을 추가하고,

수정되었다면 아이템을 찾아서 아이템을 수정하고, 삭제되었다면 아이템을 찾아 삭제해주면 되겠습니다.

이 모든 이벤트들은 listBox_log에 아이템을 추가하게 됩니다. 주의 할 점은 이벤트 발생시 ListBox 컨트롤에 접근하므로 크로스쓰레드 문제를 처리해야 합니다.

 

5.2 본격적으로 프로그래밍하기

노하우를 효과적으로 전달하기 위하여 설계와 OOP 철학에 대한 부분은 생략하도록 하겠습니다.

컴파일을 하여 Debug 폴더 생성 후 테스트를 위한 Test폴더를 생성 합니다.

Form이 Load 되었을 때, Test폴더의 파일 정보를 얻는 InitFilelist 메소드와 폴더를 감시할 개체를 생성하는 InitFileSystemWatch 메소드를 호출합니다.

InitFileSystemWatch 메서드에서는 FileSystemWatch 개체를 생성 후, 속성들의 값을 넣어주고 이벤트 핸들러를 등록 합니다.

마지막으로는 이벤트 발생 여부 속성인 EnableRaisingEvents의 값을 true로 지정해줍니다.

 

 


										

public partial class Form_filesystemwatcher : Form
										

{

    const string FolderName = "Test";

    public Form_filesystemwatcher()

    {

        InitializeComponent();

    }

 

    private void Form_filesystemwatcher_Load(object sender, EventArgs e)

    {

        InitFilelist();

        InitFileSystemWatcher();

    }

 

    private void InitFilelist()

    {

        DirectoryInfo dti = new DirectoryInfo(FolderName);

        FileInfo[] files = dti.GetFiles();

        foreach (FileInfo file in files)

        {

            listBox_filelist.Items.Add(file.Name);

        }

    }

 

    private void InitFileSystemWatcher()

    {

        FileSystemWatcher fs = new FileSystemWatcher();

        fs.Path = FolderName; 

        fs.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName; 

        fs.Filter = ""

        fs.Created += new FileSystemEventHandler(fs_Created); 

        fs.Deleted += new FileSystemEventHandler(fs_Deleted); 

        fs.Renamed += new RenamedEventHandler(fs_Renamed);    

        fs.EnableRaisingEvents = true;     }

 

 

FileSystemWatcher 개체에서 이벤트가 발생되면 AddLog 메소드를 이용해 Log를 남기고,

추가, 수정, 삭제 되었을 때의 처리를 해줍니다. 크로스쓰레드 문제를 해결 하기 위하여 delegate를 이용하였습니다.

delegate void FileListboxDele(string text, WatcherChangeTypes watcherChangeTypes);

delegate void LogListboxDele(string text);

void fs_Created(object sender, FileSystemEventArgs e)

{

    AddLog(e.FullPath, e.ChangeType.ToString());

    UpdateFileList(e.Name, e.ChangeType);

}

void fs_Renamed(object sender, RenamedEventArgs e)

{

    AddLog(e.FullPath, e.ChangeType.ToString());

    ModFileList(e.OldName, e.Name);

}

void fs_Deleted(object sender, FileSystemEventArgs e)

{

    AddLog(e.FullPath, e.ChangeType.ToString());

    UpdateFileList(e.Name, WatcherChangeTypes.Deleted);

}

 

private void AddLog(string fullPath, string eventName)

{

    string log = string.Format("Path :{0} , Event :{1}", fullPath, eventName);

    listBox_log.Invoke(new LogListboxDele(AddLog2), new object[] { log });

}

private void AddLog2(string log)

{

    listBox_log.Items.Add(log);

}

 

private void UpdateFileList(string filename, WatcherChangeTypes watcherChangeTypes)

{

    listBox_log.Invoke(new FileListboxDele(UpdateFileList2), new object[] { filename, watcherChangeTypes });

}

 

private void UpdateFileList2(string filename, WatcherChangeTypes watcherChangeTypes)

{

    switch(watcherChangeTypes)

    {

        case WatcherChangeTypes.Created: AddFileList(filename); break;

        case WatcherChangeTypes.Deleted: DelFileList(filename); break;

    }

}

 

private void AddFileList(string filename)

{

    listBox_filelist.Items.Add(filename);

}

private void ModFileList(string oldName, string name)

{

    UpdateFileList(oldName, WatcherChangeTypes.Deleted);

    UpdateFileList(name, WatcherChangeTypes.Created);

}

private void DelFileList(string filename)

{

    listBox_filelist.Items.Remove(filename);

}

 

 

 

How_to_-_지정한_폴더_감시하기.docx

 

How_to_-_지정한_폴더_감시하기.zip

+ Recent posts