본문 바로가기
C# 기술

[C#] Callback, Action으로 간단히 사용하기 (delegate 사용안함)

by bryan.oh 2021. 11. 25.
반응형

C#
Action
Callback

 

역시 설명은 예시로~

 

여러가지 경우에 쓰이지만 

아래와 같은 예를 들어보겠습니다.

 

Main Class 가 있습니다.
여기에서 Watcher 라는 클래스의 객체를 만들어서 파일 모니터링을 한다고 합니다.
특정 경로의 폴더에 어떤 파일이 생기거나 삭제되거나하면 알림을 주는건데요.

 

프로세스는 아래와 같습니다.

1. 프로그램이 실행되면 Watcher 를 띄워서 모니터링을 시작합니다.
   이때 Main Class 에서는 본인이 할일을 합니다.

2. Watcher 가 모니터링 중에 파일 생성을 감지했습니다.
   Watcher는 Main 을 호출해서 Main 에서 해당 작업을 처리해야 합니다.

 

이럴때 코드를 어떻게 만드시겠습니까?

제가 주니어였을 땐 아래와 같이 코딩했습니다. (이렇게 하지마세요ㅎㅎ)

class Main{

  private Watcher watcher;
  public Form(){
    watcher = new Watcher(this);
    watcher.start();
    
    // do something main job..
  }
        
  public void doWhenCreatedFile(string path){
    // do something..
  }

}

// ======================================================

class Watcher{
  private Main main;
  public Watcher(Main main){
    this.main = main;
    
    // FileSystemWatcher 코드 생략..
  }
  
  private void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
  {
    main.doWhenCreatedFile(e.Name);
  }
}

이러면 서로 종속성이 생기게 됩니다. 순환참조가 되는거죠.

Watcher 라는 class 는 분명 유틸성으로 재사용이 가능한 class 입니다.
하지만 다른곳에서 사용하려고 할때, Main 이라는 class 가 있기 때문에 Main도 가져가야됩니다.
아니면 Watcher2 를 만들거나? (말도안되는..)

 

Watcher 가 Main 을 호출해야하는데, Main class의 객체 없이 main 의 함수를 호출할까요?

그런걸 하는게 callback 함수죠. C# 에서는 delegateAction 등을 사용합니다.

여기에선 더 간단히 사용하고 직관적인 Action 을 사용해보려고 합니다.

위의 코드를 Action 을 써서 다시 타이핑 해보겠습니다.

 

class Main{

  private Watcher watcher;
  public Form(){
    watcher = new Watcher(doWhenCreatedFile); // 함수를 넘김
    watcher.start();
    
    // do something main job..
  }
        
  public void doWhenCreatedFile(string path){
    // do something..
  }

}

// ======================================================

class Watcher{
  // private Main main; <-- 이거 대신 아래의 callback 이 같은 일을 해줌
  private Action<string> callback;
  
  // public Watcher(Main main){ <-- main 객체는 ㅂㅂ
  // this.main = main; <-- 이것도 ㅂㅂ
  public Watcher(Action<string> callback){ // Action 을 파라메터로 받음
    this.callback = callback;
    
    // FileSystemWatcher 코드 생략..
  }
  
  private void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
  {
    // main.doWhenCreatedFile(e.Name); <-- main 객체는 이제 안녕~
    callback.Invoke(e.Name);  // Invoke 외에 비동기로 BeginInvoke도 사용가능
  }
}

 이렇게 하면 Watcher 는 Main 외에 어느 Class 에서든 Watcher 만 불러와서 사용할 수 있습니다.

 

그림으로 간략히 설명하면

첫번째 코드는 이렇습니다.

다른 클래스들은 사용할 수 있는 방법이 없죠.

두번째 코드는 아래와 같습니다.

각자 클래스들이 Action 을 만들어서 넘기기만 하면 Watcher는 그 Action 을 실행해 줍니다.

사용하기 편해야 잘 쓰죠.

 

이게 최선의 방법은 아닙니다. 여러가지 방법이 있지만 그 중 하나입니다.

다만, 첫번째 코드와 같은 방법은 안 좋은 코드입니다.

그럼

즐코딩하세요~

 

 

 

 

728x90
반응형

댓글