'전체'에 해당되는 글 225건

  1. 2011/09/28 [메모] Snippy - Visual Studio Code Snippet Editor by dalbong2
  2. 2011/04/18 [메모]HTML 부분을 컨트롤화 by dalbong2
  3. 2011/04/18 [메모]Dynamically removing/ replacing an external JavaScript or CSS file by dalbong2
  4. 2011/04/18 [메모] ASP.NET Thread Usage on IIS 7.0 and 6.0 by dalbong2
  5. 2011/03/17 세번의 만남 다큐를 보면서. by dalbong2
  6. 2011/03/07 2009 세계시민기자포럼- 뉴미디어 뉴트렌드 by dalbong2
  7. 2011/02/14 비즈니스에 영감을 주는 국내외 SNS서비스들 by dalbong2
  8. 2011/01/19 당신의 비즈니스 모델은 무엇입니까? by dalbong2
  9. 2011/01/19 Ajax & HTML UI 코딩 모델 by dalbong2
  10. 2011/01/19 SNS가 세상을 바꾼다. by dalbong2
  11. 2011/01/19 2010 창업현황 및 트렌드 분석 by dalbong2
  12. 2011/01/19 매쉬업 인증, OAuth 사용하기 by dalbong2
  13. 2011/01/19 SNS기반의 비즈니스 모델 (ppt) by dalbong2
  14. 2011/01/19 SNS기반의 취업사이트 구상(PPT) by dalbong2
  15. 2010/04/30 왜 요즘 블로그 안하냐고? by dalbong2 (3)
  16. 2010/03/29 [메모] 트랜잭션 격리 수준 정리 by dalbong2 (1)
  17. 2010/03/12 [메모] 유용한 샘플 코드들 by dalbong2
  18. 2010/03/12 [메모] 네트워크 관련 토픽 블로그 by dalbong2
  19. 2010/03/08 Spring.NET 개발 가이드 by dalbong2 (2)
  20. 2009/12/31 [메모] WCF 호출시 병목현상 관련 by dalbong2
  21. 2009/12/29 [메모] Cross-domain 해결 방법 by dalbong2
  22. 2009/12/29 [메모] Getting Started with Silverlight development by dalbong2
  23. 2009/12/03 [메모] CLR v4 Security Policy Roundup by dalbong2
  24. 2009/12/03 [메모] Tying your IE Hosted Control to a Manifest by dalbong2
  25. 2009/11/19 MIXSH인증용 새 페이지 by dalbong2
  26. 2009/10/27 [메모] White Box testing tool for .NET by dalbong2
  27. 2009/08/08 개발 프레임워크 만들기 대장정 47 - UI단 프레임워크 추가사항 by dalbong2
  28. 2009/07/20 개발 프레임워크 만들기 대장정 46 - 서비스 호출하기 by dalbong2
  29. 2009/07/20 개발 프레임워크 만들기 대장정 45 - 서비스 구성하기 by dalbong2
  30. 2009/07/20 개발 프레임워크 만들기 대장정 44 - WCF 확장하기 III ( 프로그레스바 자동 보여주기) by dalbong2

Snippy - Visual Studio Code Snippet Editor

http://snippy.codeplex.com/

저작자 표시

'개발 > .NET' 카테고리의 다른 글

[메모] Snippy - Visual Studio Code Snippet Editor  (0) 2011/09/28
[메모] ASP.NET Thread Usage on IIS 7.0 and 6.0  (0) 2011/04/18
[메모] 유용한 샘플 코드들  (0) 2010/03/12
어셈블리 바인딩 1  (3) 2009/04/23
어셈블리 바인딩 2  (0) 2009/04/23
어셈블리 구조  (0) 2009/04/23
Posted by dalbong2


Ajax를 이용한 웹 애플리케이션을 제작하다 보면 ASP.NET의 사용자 컨트롤처럼 HTML 페이지의 전체를 부분을 컨트롤화 할 수 있는 방법이 필요한 경우가 있다. 이런 경우 부분을 로딩하기 위해서 ASP.NET의 HTTP 핸들러같은 모듈을 제작할 수도 있지만, jQuery 같은 라이브러리를 사용하는 경우는, jQuery의 load, get 같은 메소드를 이용해서 쉽게 해결할 수 있다.

    $('.left-nav a').each(function() {
        var $link = $(this);
        var $dialog = $('<div></div>')
   .load($link.attr('href') ) // --> 요 부분
   .dialog({
       autoOpen: false,
       title: $link.attr('title'),
       show: "blind",
       hide: "blind", // explode, slide
       close: BizBee.Main.PostMemberInfo,
       width: 500,
       height: 300    
       
   });

        $link.click(function(ev) {
            $dialog.dialog('open');

            $('.left-nav a.selected').removeClass('selected');
            $(this).addClass('selected');
            ev.preventDefault();

            return false;
        });
    });

저작자 표시
Posted by dalbong2
html 페이지의 부분을 컨트롤처럼( asp.net 사용자 컨트롤처럼) 독립적으로 개발할때 필요해서 메모해둔다.
메인 페이지에 이미 설정된 .css, .js 파일을 html의 부분을 별도록 디자이너가 개발할 수 있도록 할때 편리하다.

http://www.javascriptkit.com/javatutors/loadjavascriptcss2.shtml 

function removejscssfile(filename, filetype){
 var targetelement=(filetype=="js")? "script" : (filetype=="css")? "link" : "none" //determine element type to create nodelist from
 var targetattr=(filetype=="js")? "src" : (filetype=="css")? "href" : "none" //determine corresponding attribute to test for
 var allsuspects=document.getElementsByTagName(targetelement)
 for (var i=allsuspects.length; i>=0; i--){ //search backwards within nodelist for matching elements to remove
  if (allsuspects[i] && allsuspects[i].getAttribute(targetattr)!=null && allsuspects[i].getAttribute(targetattr).indexOf(filename)!=-1)
   allsuspects[i].parentNode.removeChild(allsuspects[i]) //remove element by calling parentNode.removeChild()
 }
}

removejscssfile("somescript.js", "js") //remove all occurences of "somescript.js" on page
removejscssfile("somestyle.css", "css") //remove all occurences "somestyle.css" on page
저작자 표시
Posted by dalbong2

Http Request, IIS, ASP.NET, CLR Thread( Threadpool ), Application, Cpu 관계

http://blogs.msdn.com/b/tmarq/archive/2007/07/21/asp-net-thread-usage-on-iis-7-0-and-6-0.aspx 

저작자 표시

'개발 > .NET' 카테고리의 다른 글

[메모] Snippy - Visual Studio Code Snippet Editor  (0) 2011/09/28
[메모] ASP.NET Thread Usage on IIS 7.0 and 6.0  (0) 2011/04/18
[메모] 유용한 샘플 코드들  (0) 2010/03/12
어셈블리 바인딩 1  (3) 2009/04/23
어셈블리 바인딩 2  (0) 2009/04/23
어셈블리 구조  (0) 2009/04/23
Posted by dalbong2
나이가 들어서인가, 요즘은 눈시울이 뜨거워지는 경우가 많다. 말 한마디가 마음을 흔드는 경우도 있다. 
TV 프로그램 슈퍼스타K를 통해서 배출된 가수 "장재인"이 출연하고 있는 다큐를 듀얼 모니터를 이용해서 보고 있다.
이 친구를 보면서 나래이터가 "청춘"이라는 말을 내밷는다. 가슴이 찡해진다.
이제는 청춘이라는 말만 들어도 가슴이 뛰는 나이가 된것이다. 
이 친구 너무 당당하다. 인간 세계에서 살아갈 수 있는 예절이라는 형식도 갖추고 있다.  덤으로 귀염성까지도 있다. 
이제는 이런 친구들을 내가 이끌어 줘야 하는 나이인것이다. 내가 어떻게 해야 할까. 그 당당함을 유지시켜주면서도 그 야생을 지켜주면서도 인간세계에서 잘 살아갈 수 있도록 어떻게 도와줘야 하는 걸까. 이제는 새로운 고민거리가 등장하는 나이인 것이다.
저작자 표시

'Others' 카테고리의 다른 글

세번의 만남 다큐를 보면서.  (0) 2011/03/17
왜 요즘 블로그 안하냐고?  (3) 2010/04/30
MIXSH인증용 새 페이지  (0) 2009/11/19
[메모] White Box testing tool for .NET  (0) 2009/10/27
블로그 이전 완료  (1) 2009/04/25
Hundreds Island ! 들어들 봤나  (0) 2009/04/25
Posted by dalbong2
좀 지난 기사이긴 하지만 트렌드 탐구하기에는 재밌는 기사들이다. http://www.ohmynews.com/NWS_Web/ArticlePage/Special/Special_list01.aspx?pSRS_CD=0000010792
저작자 표시
Posted by dalbong2
비즈니스에 영감을 주는 국내외 SNS 서비스들

저작자 표시
Posted by dalbong2
당신의 비즈니스 모델은 무엇입니까?
View more presentations from Jungsik Yu.

JungsikYu의 다른 PPT
저작자 표시
Posted by dalbong2

Ajax를 이용하는 웹 애플리케이션의 코딩 모델은 윈폼(Windows Form)또는 웹폼의 모델과 유사합니다.

해서, 잠깐 메모를 해 둡니다.


저작자 표시
Posted by dalbong2

한국일보 기획물

http://news.hankooki.com/hotissue/gi_sr_view.php?mode=gi&parent_id=971
저작자 표시
Posted by dalbong2
TAG SNS, 트렌드
4 1.2010년창업현황및트랜드분석(황미애)

저작자 표시
Posted by dalbong2
매쉬업 인증에 사용되는 OAuth( Open Authentication )에 대한 개념을 설명합니다.
OAuth
View more presentations from 인균 황.
저작자 표시
Posted by dalbong2
TAG mashup, oath

SNS를 이용해서 어떻게 비즈니스 모델을 도출해야 하는지에 대한 나름대로의 기준/컨셉을 정리했습니다.

다음 슬라이드쇼는 www.slideshare.net과 연동됩니다.

슬라이드 화면을 크게 보고 싶으면 뷰어의 "menu > View Fullscreen" 메뉴를 이용합니다.

저작자 표시
Posted by dalbong2

SNS를 이용한 취업사이트를 구상하고 있습니다. 여러분의 코멘트 환영합니다.

참고로 슬라이드쇼는 www.slideshare.net을 이용하고 있습니다. 

저작자 표시
Posted by dalbong2

누군가 왜 요즘 블로그를 안하냐고 물었단다.

그러자 그가 대답했단다.

“오래 안쓰다 보니 뭔가 대단한 것을 써야 할 것같은 기분이 들어서”

달봉이는 그렇지는 않다. 처음부터 이 블로그는 내 블로그고 내가 남기고 싶은 내용을 정리하고 싶을 뿐이라고 생각했기때문이다.

사실 달봉이는 몇 달 전 작은 회사로 입사를 했다.

이제는 정직원의 마음 가짐으로 책임감을 갖고 해야 할 것 같은 생각 때문에 프리로 일하는 것 하고는 다른 기분이다. 

내근 프로젝트를 하고는 있어서, 사실 외부 SI 프로젝트를 뛰는 것보다는 시간적으로는 여유가 더 있기는 한데, 정신적으로는 그렇지 못하다.

나이도 있고 직책도 직책인지라 익숙하지 않은 사람들과의 팀웤도 신경써서 관리해야 하고 여러면에서 책임감의 부담이 조금은 있다.

이 생활에 하루 빨리 익숙해져서 나름대로 정신적으로도 여유를 되찾고 그래서 블로그도 다시 하고  중단된 시험 준비도 다시 시작해야겠다.

'Others' 카테고리의 다른 글

세번의 만남 다큐를 보면서.  (0) 2011/03/17
왜 요즘 블로그 안하냐고?  (3) 2010/04/30
MIXSH인증용 새 페이지  (0) 2009/11/19
[메모] White Box testing tool for .NET  (0) 2009/10/27
블로그 이전 완료  (1) 2009/04/25
Hundreds Island ! 들어들 봤나  (0) 2009/04/25
Posted by dalbong2

 

  1. Read Uncommitted
    1. 특징
      • Nolock 힌트와 동일
      • Select 구문의 이슈이다.
      • Dirty Read - 다른 Transaction에서 변경이 되었지만 아직 Commit 명령이 아직 수행되지 않은 변경된 데이터(Dirty)를 읽어올 수 있음( 수정불가).
    2. 업무 시나리오
      • Select구문에 대한 후속 작업에서 변경을 가하지 않는 로직에 적용
      • Transaction이 빈번한 테이블에서 빠른 조회가 요구될 때
      • 동시성에 대한 요구가 없는 작업에서
  2. Read Committed
    1. 특징
      • 힌트가 없는 일반 문장
      • 디폴트 격리수준
      • Select 이슈.
      • 다른 Transaction에서 변경 중인 데이터는 읽어 올 수가 없음
        (다른 Transaciton에서 Commit 또는 Rollback 명령이 떨어지지 않는 한 실행된 Select구문은 대기 상태로 들어가게 됨).
    2. 업무 시나리오
      • 대부분의 일반 업무 시나리오.
  3. Repeatable Read
    1. 특징
      • UPDLOCK힌트와 동일
      • 자신의 Transaction의 Select이슈, 다른 Transaction의 Update 이슈
      • 한 트랜잭션내에서 수행하는 select문은 항상 동일한 값을 반환함( 공유잠금유지)
      • 즉, 자신의 Transaction하에서 Select된 로우에 대해 다른 Transaction이 읽어갈 수는 있지만 수정할 수 없음.
      • 다른 Transaction이 같은 테이블의 다른 로우에 대한 변경, 추가, 삭제는 가능
      • select * , 조건절 Select이나 테이블 스캔, 인덱스 스캔인 경우는 해당 테이블에 변경, 삭제가 불가능 하나 추가는 가능
    2. 업무 시나리오
      • 같은 로우에 대한 동시 업데이트가 문제시 되는 업무 시나리오
      • 같은 로우에 대한 Transaction이 빈번한 경우 Select구문에 대한 중요 정책이 필요할 때
      • 예약, 발권 등의 같은 로우에 대한 동시 접근 시나리오.
    3. * Read Uncommitted와의 차이점은?
  4. Serializable
    1. 특징
      • HOLDLOCK힌트와 동일하다.
      • Repeatable Read 특징을 모두 포함.
      • 조건 조회의 경우는 Repeatable Read와 동일
        (해당 로우에 대해 다른 Transaction이 변경,삭제를 할 수 없음)
      • Select *, 조건조회이나 테이블 스캔, 인덱스 스캔의 경우 다른 Transaction에서 해당 테이블에 대해 변경, 삭제, 추가를 할 수 없음.
    2. 업무 시나리오
      • 한 Transaction에서 발생된 Select구문의 데이터에 대한 완벽한 정확성을 반영하고자 할 때
      • 대량의 데이터를 특정 로직으로 변경을 가하는 Import, Export, Bulk Copy 등의 배치 작업에서 데이터의 동시성이 중요시 되는 경우에 사용
      • 해당 테이블에 동시 Transaction 수가 적을 때
      • Transaction이 빈번한 대규모 시스템에서는 성능에 치명적인 영향을 미치므로 주의해서 사용

'데이터베이스' 카테고리의 다른 글

[메모] 트랜잭션 격리 수준 정리  (1) 2010/03/29
Posted by dalbong2

괜찮음 !
Mike Woodring's .NET Sample Page ( http://www.bearcanyon.com/dotnet/ )

저작자 표시

'개발 > .NET' 카테고리의 다른 글

[메모] Snippy - Visual Studio Code Snippet Editor  (0) 2011/09/28
[메모] ASP.NET Thread Usage on IIS 7.0 and 6.0  (0) 2011/04/18
[메모] 유용한 샘플 코드들  (0) 2010/03/12
어셈블리 바인딩 1  (3) 2009/04/23
어셈블리 바인딩 2  (0) 2009/04/23
어셈블리 구조  (0) 2009/04/23
Posted by dalbong2

포괄적인 네트워크 관련 토픽을 게시하고 있는 블로그이다.

명사십리( http://blog.naver.com/hjo0075?Redirect=Log&logNo=140004989745 )

'네트워크/보안' 카테고리의 다른 글

[메모] 네트워크 관련 토픽 블로그  (0) 2010/03/12
Posted by dalbong2

오랜만에 포스팅을 한다.

그동안 새로운 회사에 입사를 했다.

현재 솔루션 개발 프로젝트에 참여하고 있는데, Spring.NET을 기본 프레임워크로 선정했다.

해서 Spring.NET 개발 가이드라는 문서를 하나 작성했다.
Spring.NET이 공개소스(Apache 라이센스)이니 관련 문서도 공개를 한다.


Posted by dalbong2

WCF 서비스를 호출할때, 클라이언트 수에 따라서 병목 현상이 일어날 수 있다. 이에 대한 이해 및 설정 내용을 다루는 포스트에 대한 링크들이다.

 

How to throttle a Wcf service, help prevent DoS attacks, and maintain Wcf scalability

 

Throttling in WCF  InstanceContextMode, ConcurrencyMode, and Server-side Threading

Posted by dalbong2
실버라이트에서의 Cross domain 해결

실버라이트도 웹 클라이언트 기술이기 때문에 클라이언트측의 웹 브라우저의 보안 샌드 박스에서 실행된다. 또한 웹 사이트 접근 제한 정책에 영향을 받는다. 그중의 하나가 하나가 바로 Cross-domain 접근 제한이다.

이게 뭐냐면, 한 domain에서 호스팅이되고 있는 웹 애플리케이션이 다른 domain에서 호스팅되고 있는 애플리케이션에는 기본적으로 접근할 수 없다는 것이다.

그러나 웹 애플리케이션에서 특정 도메인으로부터의 접근을 허용해주는 방법이 있다. cross-domain 정책 파일로 알려진 xml 파일을 이용하면 이런 접근에 대한 제한을 해제할 수 있다.

clientaccesspolicy.xml

crossdomain.xml

서비스를 제공하는 웹 애플리케이션에서 cross-domain 접근 제한을 해제해 주기 위해서, 이 두 파일을 어떻게 이용하는지 위 링크의 비디오에서 설명해준다.

다운로드 : How to Use Cross Domain Policy Files With Silverlight
Win Video X Domain Policy
View more videos from 인균 황.
ajax 애플리케이션에서의 cross domain 해결
http://greatkim91.tistory.com/107 ( 원문 : http://snook.ca/archives/javascript/cross_domain_aj/ )
Posted by dalbong2

Microsoft Silverlight 사이트

Get started building silverlight 3 applications

A blog by Tim Heuer

Getting started with silverlight development

Posted by dalbong2

.NET Security Blog

이 블로그의 주인이 어떤 사람인지는 모르겠지만, 이 포스트들을 읽다 보면 재밌다. 그래서 자주 들러보는 블로그중의 하나다.
이번에도 이 블로그에 올라온 글을 하나 메모해 두려 한다.

CLR v4 Security Policy Roundup
저작자 표시
Posted by dalbong2
.NET Security Blog에서 있는 포스트이다.

Tying your IE Hosted Control to a Manifest

I talked about the Orcas feature which allows you to provide a manifest to elevate your control's permissions declaratively.  We also saw how to generate manifests that would state what permissions your control needs (and the rules associated with those manifests).  Now it's time to tie it all together and create an HTML page that has a control and its associated manifests.
저작자 표시
Posted by dalbong2

KygnjE5KWHVT4TUvNje7zmd0Ck7WR0_1ijq4FxstZDc,

'Others' 카테고리의 다른 글

세번의 만남 다큐를 보면서.  (0) 2011/03/17
왜 요즘 블로그 안하냐고?  (3) 2010/04/30
MIXSH인증용 새 페이지  (0) 2009/11/19
[메모] White Box testing tool for .NET  (0) 2009/10/27
블로그 이전 완료  (1) 2009/04/25
Hundreds Island ! 들어들 봤나  (0) 2009/04/25
Posted by dalbong2

웹 서핑을 하다, vs 2008 용 테스트 툴을 보게 되서 메모해둔다.

 

Getting started with Pex in Visual Studio 2008

( http://channel9.msdn.com/posts/Peli/Getting-started-with-Pex-in-Visual-Studio-2008/ )

 

“Pex”로 검색을 해 보니, MS 에반젤리스트들의 IT블로그에 툴을 사용하는 법도 정리되어 있다.

 

.NET White Box Testing 도구, PEX (Program EXploration)

( http://blogs.msdn.com/eva/archive/2009/01/28/net-white-box-testing-pex-program-exploration.aspx )

'Others' 카테고리의 다른 글

왜 요즘 블로그 안하냐고?  (3) 2010/04/30
MIXSH인증용 새 페이지  (0) 2009/11/19
[메모] White Box testing tool for .NET  (0) 2009/10/27
블로그 이전 완료  (1) 2009/04/25
Hundreds Island ! 들어들 봤나  (0) 2009/04/25
여기는 바기오 !  (0) 2009/04/25
Posted by dalbong2

UI단 프레임워크가 거의 완성되었다. 그러나 고려해봐야 할 녀석들이 몇 가지 있다. 달봉이가 참여한 프로젝트가 빡빡한 일정때문에 힘들어지고 있다. 아마 당분간은 정리가 힘들것 같다.  생각나는 대로 메모를 해 둬야겠다. 요즘은 메모를 해 두지 않으면 금방 잊어버린다. 이러다가 영화 “메멘토” 수준으로 될 것 같은 기분이 요즘 든다.

 

-업무 화면의 베이스 클래스 타입

-업무 화면 객체의 출력 컨트롤

-화면 객체의 라이프사이클

-서버측 서비스 환경 설정

-사용자 정보 객체의 사이트별 확장

 

 

■업무 화면의 베이스 클래스 타입

WPF의 루트 요소를 고려해서 UserControl, Page  두 종류의 베이스 클래스가 있어야 할 것 같다.

 

■업무 화면 객체의 출력 컨트롤

두 종류의 업무 화면 베이스 클래스를 출력할 수 있으려면? Frame 객체 사용 고려

 

■화면 객체의 라이프사이클

화면 종료시, 객체 저장소에서의 화면 객체 제거 여부 결정하기

메모리 사용량과 관련

 

■서버측 서비스 환경 설정

계층 구조로 구성된 WCF 서비스 애플리케이션에서 공통 확장 모듈에 대한 configuration을 어떻게 할 것인가.

 

■사용자 정보 객체의 사이트별 확장

달봉이 프레임워크의 코드를 수정하지 않고, 사이트별로 확장된 사용자 정보 및 개인 권한 정보 객체를 애플리케이션에서 사용할 수 있도록 등록할 것인가?

 

이상

Posted by dalbong2

이제 클라이언트에서 달봉이가 만들어놓은 프락시 팩토리를 이용해서 서비스를 호출해보자.

 

■ 서비스 참조 추가하기

 

우선 서비스에 대한 참조를 클라이언트 프로젝트에서 추가하자. BONG.WIN.CO.UserMgmt 프로젝트의 References 노드를 오른쪽 클릭해서 “Add Service Reference…”를 선택한다.

그럼 다음과 같은 서비스 참조 추가 창이 뜬다.

Address 박스에 이전 포스트에서 봤던 주소를 복사해 넣는다.

그런 다음 “Go”버튼을 클릭한다. 그럼 앞의 그림처럼 SampleService가 보이게 된다. 이제 Namespace 텍스트박스에 “SampleAsyncService”라 입력한다.

그리고 마지막으로 “Advanced…”버튼을 클릭한다.

그래서 Generate aysnchronous operations 체크박스를 선택한다.

이렇게 해서 참조 추가를 마친다. 이렇게 하면 Visual Studio는 클라이언트에서 사용할 수 있는 SampleService를 동기와 비동기적으로 호출할 수 있는 메소드를 갖는 프락시 클래스를 자동으로 생성해준다. 달봉이 프락시 생성 팩토리는 이 자동 생성 프락시를 사용하게 된다.

 

■ 업무 화면 준비

 

이제 업무 화면에 버튼을 하나 올려놓고 버튼을 클릭했을때 실행될 이벤트 핸들러를 작성해보자. UserMgmt.xaml 마크업 코드는 다음과 같이 되어 있다.

<Bong:BongControlBase x:Class="BONG.WIN.CO.UserMgmt.UserMgmt"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:Bong="clr-namespace:Bong.Win;assembly=Bong.Win"

    Height="Auto" Width="Auto">

    <Border BorderBrush="Black" BorderThickness="2">

        <StackPanel>

            <Button Height="23" Name="btnHello" Width="75" Click="btnHello_Click">Hello</Button>

            <TextBlock Name="tbReply"></TextBlock>

        </StackPanel>

    </Border>

</Bong:BongControlBase>

 

■동기호출

 

이제 달봉이가 만들어놓은 프락시 팩토리 객체를 이용해서 서비스를 호출할 차례다.

먼저 동기로 호출하는 코드이다. 이것은 심플하다.

 BongServiceProxyFactory<SampleAsyncService.ISampleService> sampleProxyfactory = null;

SampleAsyncService.ISampleService asyncServiceProxy = null;

 string strHello = "";

 private void btnHello_Click(object sender, RoutedEventArgs e)

{

     //동기호출

     this.tbReply.Text = "";

     try

     {

         sampleProxyfactory = new BongServiceProxyFactory<SampleAsyncService.ISampleService>();

         asyncServiceProxy = sampleProxyfactory.GetServiceProxy("BaseUrlOfCOService",

             "BONG.CO.UserMgmt.Service/SampleService.svc"); //, this);

         strHello = asyncServiceProxy.Hello();

     }

     catch

     {

         //예외 처리

     }

     finally

     {

         sampleProxyfactory.Close();

     }

     //결과값 이용

     this.tbReply.Text = strHello;

 

BongServiceProxyFactory<T>를 생성한다. 개발자가 사용할 서비스에 대한 프락시 객체를 생성해줄 공장(?)이다. 그 다음 그 팩토리 객체를 이용해서 SampleService에 대한 주소를 건네주고 서비스에 대한 프락시 객체를 건네받는다.

이때 마지막 인자로 this를 넘겨줘도 상관없지만 내부적으로는 서비스 시작과 끝을 알리는 이벤트가 발생하지만 겉으로 보기에는 아무일도 일어나지 않는다. 프로그레스바도 나타나지 않는다. 왜? 동기호출이니까. (물론 동기 호출이라도 프로그레스바를 보여주는 방법은 있다. 프로그레스바를 보여주는 또다른 쓰레드를 만들어서 사용할 수도 있지만, 이렇게 프로그레스바를 보여주는 방법은 그닥 사용자가 보기에는 좋지 않다. 어플리케이션과 프로그레스바가 따로 따로 논다. 좋지 않다.)

서비스 프락시 객체 asyncserviceProxy에서 점을 찍으면 인텔리센스 기능에 의해 다음과 같은 호출 가능한 메소드 후보들이 나타난다.

이 중에서 Begin, End로 시작하는 Hello() 버전은 동기를 위한 것이고, Hello()가 동기 호출을 위한 것이다.  Hello() 를 선택한다. 이제 서비스를 호출하고 결과값을 반환받아서 필요한대로 사용하면 된다. 코딩은 앞에서처럼 try~catch~finally식으로 하면 된다.

 

■ 비동기 호출

 

다음은 비동기 호출을 위한 코딩 패턴이다. 개발자가 비동기 호출을 할때는 서비스를 호출하는 부분과 결과값을 처리하는 부분을 분리해서 작성해야 한다.

복잡한 듯 보이지만 다음 패턴대로만 한다면 그렇게 복잡한 것도 아니다.

BongServiceProxyFactory<SampleAsyncService.ISampleService> sampleProxyfactory = null;

SampleAsyncService.ISampleService asyncServiceProxy = null;

string strHello = "";

private void btnHello_Click(object sender, RoutedEventArgs e)

{

    //비동기호출

    //서비스 호출하는 부분

    this.tbReply.Text = "";

    sampleProxyfactory = new BongServiceProxyFactory<SampleAsyncService.ISampleService>();

    asyncServiceProxy = sampleProxyfactory.GetServiceProxy("BaseUrlOfCOService",

        "BONG.CO.UserMgmt.Service/SampleService.svc", this);

    AsyncCallback callback = new AsyncCallback(HelloCallback);

    //서비스 프락시 객체를 서버측으로 보낸다.

    asyncServiceProxy.BeginHello(callback, asyncServiceProxy);

}

이 부분이 서비스를 비동기로 호출하는 부분이다. 서비스 프락시 객체 asyncServiceProxy의 BeginHello() 메소드를 호출하고 있다. 이 메소드가 호출되고 나서 UI 쓰레드( 현재 메소드를 호출하는 쓰레드)는 이곳에서 서비스 답변을 기다리지 않는다. 그냥 호출만 하고 자신은 계속 실행을 진행한다. 앞의 코드에서는 서비스를 호출하고 나서 아무 일도 하지 않고 그냥 btnHello_Click() 메소드가 종료될뿐이다. 이때 내부적으로는 쓰레드가 하나 새롭게 하나 생성되어서 서비스 호출을 담당하게 된다.

BeginHello() 메소드에 두 개의 인자를 넘겨주고 있다. 서비스를 호출하는 부분에서는 서비스 답변을 기다리지 않고 그냥 종료되었으므로 그 결과를 처리할 부분을 프레임워크에 알려줘야 한다. 첫번째 인자가 그 답변을 처리할 곳에 대한 정보를 제공하는 역할을 한다. HelloCallback이라는 메소드에서 비동기적으로 호출한 서비스의 답변을 기다리겠다는 의미로 HelloCallback 메소드를 프레임워크에게 알려줘야 하는데 그냥 건네주면 프레임워크는 인식할 수 없다. AsyncCallback이라는 것으로 한번 감싸서 보내줘야 한다. 첫번째 인자 callback의 의미는 그렇다.

두번째 인자로 asyncServiceProxy 객체를 넘겨주고 있는데 서비스 메소드를 호출하는 프락시 객체 자신을 넘겨주고 있다. 두번째 인자는 원래 결과값을 처리하는 곳으로 어떤 특별한 값을 보내고 싶을때 사용한다. 이곳에 값을 넘겨주면 서비스 작업 호출 후 프레임워크에서는 결과값을 받는 메소드 HelloCallback을 호출할 때 그 값을 그대로 건네준다. 이곳에서는 서비스 프락시 객체 asyncServiceProxy 자신을 그대로 콜백 함수에 넘겨주겠다는 것이다. 그럼 콜백 함수에서 하는 일을 보도록 하자.

/// <summary>

/// 결과값 처리하는 부분

/// </summary>

/// <param name="result"></param>

private void HelloCallback(IAsyncResult result)

{

    if (result.IsCompleted)

    {

        if (!this.Dispatcher.CheckAccess())

        {

            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,

            new AsyncCallback(HelloCallback), result);

            return;

        }

        try

        {

            //서버측으로 보낸 서비스 프락시 객체를 복원한다.

            asyncServiceProxy = (SampleAsyncService.ISampleService)result.AsyncState;

            strHello = asyncServiceProxy.EndHello(result);

            this.tbReply.Text = strHello;

        }

        catch (Exception e)

        {

            //예외처리

            MessageBox.Show(e.Message);

        }

        finally

        {

            sampleProxyfactory.Close();

        }

    }

}

콜백 함수 HelloCallback 메소드는 프레임워크로부터 인자를 하나 받는다 : IAsyncResult 타입의 result객체. 콜백함수에서는 서비스 호출이 종료되었는지를 확인해서 다음 작업을 해 줘야 하는데, 서비스 호출 종료는 코드에서처럼 result객체의 IsCompleted 속성을 통해서 확인할 수 있다.

그 다음 볼드체 부분에서 하는 일은 이렇다. 앞에서 서비스를 비동기로 호출하면 내부적으로 쓰레드가 하나 생성되고 그곳에서 서비스 호출이 실행된다고 했다. 그 새로운 쓰레드에서 콜백함수 HelloCallback 메소드를 호출하고 있다. 그러나 UI 컨트롤들에 접근하기 위해서는 원래의 쓰레드로 돌아와야 한다. this 즉 UserControl의 Dispatcher를 통해서 현재 호출하는 쓰레드가 UserControl이 속한 쓰레드와 일치하는지를 확인하고 있다. 만약 쓰레드가 달라서 UI 컨트롤에 접근할 수 없다고 판단되면 다시 Dispatcher의 BeginInvoke()를 호출해서 다른 쓰레드를 통해서 HelloCallback 함수를 다시 호출한다. BeginInvoke()를 호출할때 콜백함수를 인자로 넘겨주는 이유이다. 이런 작업을 UI 쓰레드에 도착할때까지 반복하는 것이다. 최종적으로 UI 쓰레드에 도착해서 this.Dispatcher.CheckAccess() 확인 작업을 통과하고 나면 이후의 코드가 실행될 수 있다.

첫번째 작업은 result 객체의 AsyncState 속성을 호출하고 있는데, 이 속성을 통해서 이전에 서비스를 호출할때 넘겨준 서비스 프락시 객체 asyncServiceProxy를 복원할 수 있다. 이 복원된 객체를 통해서 EndHello() 메소드를 호출하는데 이로써 서비스 호출 결과를 받을 수 있다. 결과를 받아서 이제 필요한대로 사용하면 된다.

처음에는 asyncServiceProxy 객체를 넘겨 받지 않고 원래의 객체에 직접 접근했었다. finally 블록에 보면 sampleProxyfactory 객체는 서비스를 호출할때 넘겨서 받지 않고 원래의 객체에 직접 접근하고 것처럼. 그랬더니 가끔가다 에러가 발생했는데, 이 에러가 항상 발생하는 것은 아니었다. 어쩌다 에러가 발생하는데 에러 내용이 뭐였는지 기억이 나지 않아서 지금 재현해볼려니까 또 발생하지 않는다. 써글… 다음에 발생하면 이 부분에 대해서 보완하도록 하겠다. 이 포스트는 여기서 끝내야 겠다.

어휴…힘들다.

다음에는 Spring.NET을 이용해서 비즈니스 레이어에서 트랜잭션을 처리하는 방법과 데이터베이스에 접근하는 방법을 해 볼까 한다.

Posted by dalbong2

이번 포스트부터는 달봉이가 제작한 ServiceProxyFactory 객체를 이용해서 동기 호출과 비동기 호출에 대한 코딩 예를 보여준다.

 

■ IIS 서비스 환경 구성하기

 

우선 서버측 서비스를 구성해 보자. 달봉이는 서비스 구현 프로젝트와 서비스 노출 프로젝트를 분리했다. 서비스 구현은 BONG.SVC.CO.UserMgmt에 있고, 노출 프로젝트는 웹 애플리케이션을 이용한다.

SampleService.cs에는 다음처럼 간단한 서비스가 구현되어 있다. 다음 코드는 사용자 정보를 서버측으로 전달하는 과정을 설명하는 포스트에서도 봤다.

namespace BONG.SVC.CO.UserMgmt

{

    [ServiceContract]

    public interface ISampleService

    {

        [OperationContract]

        string Hello();

    }

    public class SampleService : Dalbong2ServiceBase, ISampleService

    {

        public string Hello()

        {

            //실행 좀 멈춘다.

            System.Threading.Thread.Sleep(10000);

            //현재 사용자의 ID를 사용한다

            return String.Format("Hello, you're {0}", base.UserInfo.ID);

        }

    }

}

이제 이 서비스를 외부로 노출시키자. 달봉이는 이 WCF 서비스 노출을 위해서 IIS를 이용하고 있다.

탐색기를 열어 달봉이의 폴더 구조를 보면 다음과 같이 되어 있다.

03 SVC 폴더를 기본 웹 사이트의 가상 디렉토리로 만들었다.

달봉이는 가상 디렉토리명을 “BongSvc”로 했다.

다음 CO 폴더를 보면 WCF 구현을 포함하고 있는 BONG.SVC.CO.UserMgmt 폴더가 있다. 이제 이것을 노출할 서비스를 만들기 위해서 BONG.CO.UserMgmt.Service폴더를 하나 더 만들자.

이제 IIS 관리 콘솔에서 BONG.CO.UserMgmt.Service에 대한 웹 애플리케이션을 하나 만들자. IIS 관리 콘솔에서 BONG.CO.UserMgmt.Service를 오른쪽클릭하면 다음과 같은 메뉴가 보인다.

이 중에서 “Convert to Application” 메뉴를 선택한다. 다음과 같은 애플리케이션 추가 창이 뜬다.

다른 값은 기본값을 사용하고, Application pool을 다른 값으로 선택할 수도 있다.

달봉이는 DalbongAppPoos( 미스 스펠링 –_-;;)을 미리 만들어 두었다. 하지만 지금은 DefaultAppPool을 사용해도 상관없다.

OK버튼을 클릭하면 다음처럼 애플리케이션이 생성된다.

이제 Visual Studio로 가자. UserMgmt 폴더를 오른쪽 클릭해서 “New Web Site…”를 선택한다.

 

템플릿에서 “WCF Service”를 선택한다.

“Browse…”버튼을 클릭해서 앞에서 만들어 놓은 웹 애플리케이션을 선택한다.

작업을 마치고 나면 Visual Studio는 다음처럼 된다.

샘플로 WCF 구현을 만들어놓은 IService.cs와 Service.cs, Service.svc가 있다.  달봉이는 이미 BONG.SVC.CO.UserMgmt에 서비스를 구현해 놨다. 해서 앞의 녀석들을 삭제한다. WCF 서비스 프로젝트를 오른쪽 클릭해서 새 항목을 추가하도록 하자.

WCF Service 템플릿을 선택하고 페이지 이름을 “SampleService.cs”로 한다. 자동 생성되는 ISampleService.cs, SampleService.cs 파일을 삭제한다.

이제 서비스를 구현해 놓은 BONG.SVC.CO.UserMgmt에 대한 참조를 추가하자. WCF 프로젝트를 선택해서 오른쪽 클릭을 한 다음 “Property pages”를 선택한다.

“Add…”버튼을 클릭한다.

Projects 탭에서 BONG.SVC.CO.UserMgmt를 선택한다.

이제 SampleService.svc 페이지를 더블 클릭하면 다음과 같은 서비스 선언문이 나타난다.

<%@ ServiceHost="" Language="C#" Debug="true" Service="SampleService" CodeBehind="~/App_Code/SampleService.cs" %>

Codebehind 부분을 제거하고, 다음처럼 수정한다.

<%@ ServiceHost="" Language="C#" Debug="true" Service="BONG.SVC.CO.UserMgmt.SampleService"  %>

이제 Web.config 파일을 수정해야 한다.

<system.serviceModel>

    <behaviors>

        <serviceBehaviors>

            <behavior name="SampleServiceBehavior">

                <serviceMetadata httpGetEnabled="true" />

                <serviceDebug includeExceptionDetailInFaults="false" />

            </behavior>

        </serviceBehaviors>

    </behaviors>

    <services>

        <service behaviorConfiguration="SampleServiceBehavior" name="BONG.SVC.CO.UserMgmt.SampleService">

            <endpoint address="" binding="wsHttpBinding" contract="BONG.SVC.CO.UserMgmt.ISampleService">

                <identity>

                    <dns value="localhost" />

                </identity>

            </endpoint>

            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

        </service>

    </services>

</system.serviceModel>

볼드체로 되어 있는 부분이 SampleService, ISampleService로 되어 있을 것이다. 이 녀석들을 위 코드처럼 수정한다. 서비스 선언문의 Service 어트리뷰트값과 web.config의 <service>의 name 어트리뷰트값이 일치해야 한다.

이제 Visual Studio에서 SampleService.svc 항목을 오른쪽 클릭해서 View in browser를 선택한다. 제대로 되었다면 다음과 같은 페이지가 출력된다.

이제 서버측 서비스 구성은 다 끝났다. 브라우저에 보이는 주소를 복사해뒀다가 클라이언트에서 서비스를 참조할때 사용하면 된다.

 

■ WCF 서비스 확장 설정하기

 

앞의 web.config에 이전 포스트에서 보았던 사용자 정보를 받기 위한 configuration을 추가한다. 그럼 완전한 <system.serviceModel/>모습은 다음과 같이 된다.

<system.serviceModel>

    <services>

        <service behaviorConfiguration="SampleServiceBehavior"

                 name="BONG.SVC.CO.UserMgmt.SampleService">

            <endpoint address=""

                      binding="wsHttpBinding"

                      behaviorConfiguration="MyEndPointInspectors"

                      contract="BONG.SVC.CO.UserMgmt.ISampleService">

                <identity>

                    <dns value="localhost" />

                </identity>

            </endpoint>

            <endpoint address="mex"

                      binding="mexHttpBinding"

                      contract="IMetadataExchange" />

        </service>

    </services>

    <behaviors>

        <serviceBehaviors>

            <behavior name="SampleServiceBehavior">

                <serviceMetadata httpGetEnabled="true" />

                <serviceDebug includeExceptionDetailInFaults="false" />

            </behavior>

        </serviceBehaviors>

        <endpointBehaviors>

            <behavior name="MyEndPointInspectors">

                <UserInfoEndpointExtention/>

            </behavior>

        </endpointBehaviors>

 

    </behaviors>

 

   <extensions>

        <behaviorExtensions>

            <add name="UserInfoEndpointExtention"

                 type="Dalbong2.Service.Interceptors.UserInfoBehaviorExtensionElement, Dalbong2.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

        </behaviorExtensions>

    </extensions>

</system.serviceModel>

한가지 주의할 것이 있다.

마지막 부분에서 type 어트리뷰트값이 길지만, 타입명과 어셈블리명 사이를 반드시 같은 줄에 적어줘야 한다. 뿐만 아니라 타입명과 어셈블리명 사이에 반드시 하나의 공백을 둬야 한다. 안그러면 고생 좀 하게 될 것이다. 달봉이가 보기에는 뭐 특별한 이유가 있는 것이 아니라, configuration 컴파일러 개발자가 빨리 만들고 어디 놀러갈 일이 있었나 보다. 덕분에 달봉이 많이 고생했다.

이것으로 서버측 서비스 설정은 끝났다. 다음 포스트에서는 클라이언트측에서의 서비스 호출을 알아보도록 한다.

Posted by dalbong2

■ 프로그레스바 출력 시나리오

 

프로그레스바 자동 출력 기능을 위해서 달봉이는 다음과 같은 시나리오를 정의했다.

프로그레스바를 보여주는 경우를 생각해보자. 이 녀석은 서비스를 호출할때마다 보여줘야 할까? 달봉이는 아니라고 생각하고 달봉이 개발 프레임워크를 구현했다. 예를 들어 업무성 코드 목록을 가져와서 드롭다운 리스트를 채우거나 사용자에게 보여줄 메세지를 가져오는 경우라면 프로그레스바 없이 내부적으로 조용히 처리하면 될 것이다. 달봉이는, 서비스 호출 결과가 늦어질 가능성이 있는 경우에만 프로그레스바를 보여주자고 결정했다.

프로그레스바 보여주는 것과 관련해서 또 한가지 달봉이가 결정한 것은 프로그레스바를 보여줄 정도로 시간이 걸리는 작업은 비동기로 구현하겠다는 것이다. 서비스 호출하고 나서 사용자를 아무 반응도 않는 애플리케이션을 바라보고만 있도록 하는 것은 바람직하지 않는 듯하다. 탭을 선택해서 다른 화면을 볼 수도 없다. 너무 답답한 일이다.

그리고 달봉이는 프로그레스바를 보여주지 않아도 되는 서비스 호출의 경우는 동기를 쓰도록 하겠다. 그러나 강제적으로 개발 프레임워크단에서 제한할 수 있는 방법은 없다. 어떤 방식의 호출을 사용할지는 개발자의 선택에 달려있다. 다만 달봉이가 제공하는 프락시 팩토리 객체는 동기와 비동기 호출을 할 수 있는 방법을 모두 제공해줄 뿐이다. 업무적인 시나리오에 맞게 개발자가 적절한 호출을 선택해야 할 것이다.

그리고 또 한가지 프로그레스바는 업무 화면 객체별로 그 상태를 가지게 될 것이다. 여러 개의 웹 페이지가 각각의 탭으로 열려있는 웹 브라우저를 생각해보자. 하나의 페이지에서 서버에 요청을 보내면 브라우저의 상태바에 프로그레스바가 출력된다. 그러나 다른 페이지의 탭을 선택하면 프로그레스바가 사라지고 현재 선택된 페이지의 진행상태에 따라서 프로그레스바의 출력 여부가 결정된다. 달봉이는 이 시나리오를 염두에 두고 구현을 했다.

 

■ 관련 클래스들

 

프로그레스바를 개발자의 코딩없이 보여줄 수 있도록 구현된 달봉이의 코드를 보도록 하자. 몇 개의 타입이 다시 정의되거나 새롭게 정의된다. 복잡하다.

 ServiceCallNotigyBehavior

Dalbong2.ServiceClient 프로젝트의 ServiceCallNotifyClientEndpointBehavior.cs에 정의되어 있다.

이 녀석이 WCF 런타임에 등록될 behavior이다. 달봉이는 “ServiceCallNotify” behavior라 부르기로 했다. 서비스 호출이 시작되거나 종료될때 위에 정의에 두 이벤트를 발생시켜준다.

 Dalbong2ProxyFactory1

Dalbong2.ServiceClient 프로젝트의 Dalbong2ProxyFactory.cs에 정의되어 있다.

이 녀석은 ServiceCallNotify behavior를 WCF 런타임이 인식할 수 있도록 behavior 목록에 등록시켜준다. 또한 ServiceCallNotify에서 발생한 이벤트를 클라이언트 코드에 전달해주는 역할을 한다. 이를 위해서 Start, End에 해당하는 자신만의 이벤트 멤버를 가지고 있다.

 BongServiceFactory

이 녀석부터 차즘 UI 컨트롤과 접촉을 시도하는 부분이다. 이 녀석이 Bong.Win 프로젝트에 정의되어 있는 이유이다. 우선 이 녀석은 화면 객체에 대한 참조를 받는다. 뒤에서 보겠지만 화면 객체들은 IProgressBarPerceptible 인터페이스를 구현하고 있다. 개발자는 서비스 호출시 프로그레스바를 보여주고 싶다면 서비스 프락시 객체를 생성할때 IProgressBarPerceptible 객체를 받는 프락시 객체 생성 메소드를 이용해야 한다.

public TService GetServiceProxy(string baseAddressKey,

string relativeAddress,

IProgresssBarPerceptible progressBarPerceptibleElement )

세번째 인자로 IProgressBarPerceptible 객체를 넘겨준다. 보통 업무 화면에서 이 메소드를 사용해서 서비스를 호출할때는 this를 넘겨주면 된다. 달봉이의 모든 업무 화면 객체는 IProgressBarPerceptible 인터페이스를 구현하고 있기때문이다.

 IProgressBarPerceptible

BongServiceProxyFactory는 Dalbong2ProxyFactory 객체로부터 서비스 호출 시작/종료에 대한 알림을 받으면 GetServiceProxy() 메소드를 통해서 받은 IProgressBarPerceptible 객체의 속성을 변경시켜준다. 우선 서비스 호출이 시작되었음을 WhileCallingService 속성과 ProgressBarVisibility값을 true로 변경시켜준다.

만약 프로그레스바를 보여주고 싶지 않다면 다음 버전의 프락시 객체 생성 메소드를 사용해야 한다.

public TService GetServiceProxy(string baseAddressKey, string relativeAddress)

업무성 코드나 메세지값을 받아 올때는 두번째 버전을 사용하면 되겠다.

다음은 업무 화면의 베이스 클래스의 정의이다.

 Dalbong2ControlBase

Dalbong2ControlBase 클래스는 그림처럼 IProgressBarPerceptible을 구현하고 있다. 또한 BongServiceProxyFactory가 설정하는 ProgressBarVisibility 속성이 변경되면 ProgressBarVisibleChanged 이벤트가 발생한다.

 

■ 프로그레스바 컨트롤 접근

 

프로그레스바 컨트롤은 업무 화면에서 직접 접근하는 것이 아니다. 단지 업무화면 객체에서는 WhileCallingService 속성과 ProgressBarVisibleChanged 이벤트만을 노출시켜준다. 화면이 전환되거나 또는 서비스 호출이 종료되어 업무 객체의 ProgressBarVisibility 속성이 변경되어 ProgressBarVisibleChanged 이벤트가 발생했을때 그 변화를 감지해서 프로그레스바 컨트롤에 직접 접근해서 그 visible 상태를 변경시켜주는 것은 UI 컨트롤에서 담당한다.

 ProgressBarVisibility

이런 구조로 가면, 사용자 정의 프로그레스바 컨트롤을 사용하더라도 그것을 직접 참조하고 있는 UI 컨테이너만 수정되면 된다. UI 컨테이너가 프로그레스바의 Visible 상태를 변경하기 위해서 그 컨트롤에 직접 직접하는 경우는 두 가지이다.

 

■ 프로그레스바 컨트롤 visible 상태 변경 경우

 

우선 사용자가 화면 탭을 전환해서 현재 보여주는 화면이 변경되는 경우이다. 사용자가 화면 A에서 화면 B로 전환할때 현재는 탭 컨트롤의 SelectionChanged 이벤트 핸들러를 이용하고 있다.

/// <summary>

/// 탭 컨트롤, 탭변경시 작업

/// 1. 프로그레스바 Visibility 변경

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void tabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e)

{

    // 프로그레스바 보여주기/숨기기

    TabItem tabItem = (sender as TabControl).SelectedItem as TabItem;

    if (tabItem == null) return;

    //tabItem의 Tag 객체에 저장해둔 업무 화면 객체를 IProgressBarPerceptioble로 변환한다.

    IProgresssBarPerceptible element = tabItem.Tag as IProgresssBarPerceptible;

    if (element != null)

    {

        //현재 업무 화면이 서비스 호출중인지를 확인해서,

        //프로그레스바 컨트롤에 접근해서 visible 상태를 변경한다.

        if( element.WhileCallingService  )

            this.ProgressBar.Visibility = Visibility.Visible;

        else

            this.ProgressBar.Visibility = Visibility.Hidden;

    }

    else

    {

        this.ProgressBar.Visibility = Visibility.Hidden;

    }

}

UI 컨테이너가 프로그레스바 컨트롤의 visible 상태를 변경하기 위해서 직접 접근하는 경우로는 업무 화면 객체가 ProgressBarVisibleChanged 이벤트를 발생시켰을 경우이다.

UI 컨테이너는 이 이벤트를 받기 위해서 업무 화면 객체가 생성해서 탭 컨트롤에 출력할때 그 핸들러를 등록하고 있다. 업무 화면 객체를 Spring.NET 컨테이너에서 가져와서 탭 컨트롤에 추가하는 코드는 이전에 보았다. 이 작업은 메뉴 트리 컨트롤의 MouseUp 이벤트에서 하고 있다. 이 코드는 Shell.cs에 포함되어 있다.

void treeItem_MouseUp(object sender, MouseButtonEventArgs e)

{

    TreeViewItem item = sender as TreeViewItem;

    //Tag 속성에 메뉴 정보 객체 복원

    FileMenuItemInfo menuInfo = item.Tag as FileMenuItemInfo;

    if (menuInfo != null)

    {

        string elemetName = menuInfo.ElementInfo.ID;

 

        IDalbong2Element existingElementInfo = null;

        //이미 같은 화면이 로딩되어 있는지 확인

        //이미 로딩되어 있다면 탭을 생성하지 않고 리턴

        <중략…>

        // Spring.NET 객체 생성기를 통해서 화면 객체를 얻는다.

        Dalbong2ControlBase  uiElement =

            ( Dalbong2ControlBaseBongWinAppContext.XmlObjectFactory.GetObject(elemetName);

       uiElement.ProgressBarVisibleChanged +=

            new ProgressBarVisibleChangedEventHandler(uiElement_ProgressBarVisibleChangedEvent);

 

        <중략…>

 

 

        //탭을 탭 컨트롤에 추가한다.

        this.tabControl1.Items.Add(tabItem);

 

        tabItem.IsSelected = true;

    }

}

UI컨테이너의  uiElement_ProgressBarVisibleChangedEvent 핸들러는 다음과 같이 구현되어 있다.

/// <summary>

/// 화면객체 로딩시, 프로그레스바 Visibility 변경

/// This method checks to see if the current thread needs to be marshalled

/// to the correct (UI owner) thread. If it does a new delegate is created

/// which recalls this method on the correct thread

/// </summary>

/// <param name="sender"></param>

/// <param name="arg"></param>

void uiElement_ProgressBarVisibleChangedEvent(object sender, ProgressBarVisibleChangedEventArgs arg)

{

    if (!this.Dispatcher.CheckAccess())

    {

        this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,

        new ProgressBarVisibleChangedEventHandler(uiElement_ProgressBarVisibleChangedEvent),

        sender, arg);

        return;

    }

 

    // 어떤 화면 객체에서 이벤트를 발생했고,

    // 어떤 이벤트 인자를 넘겼는지를 구한다.

    IDalbong2Element element = sender as IDalbong2Element;

    Visibility visibility = arg.Visibility;

    if (this.CurrentElement != null)

    {

        if (this.CurrentElement.ElementInfo.ID == element.ElementInfo.ID)

        {

            this.ProgressBar.Visibility = visibility;

        }

    }

}

첫번째 이탤릭체로 되어 있는 부분은 다음 포스트에서 비동기 호출을 보면서 다시 보게 될 것이다. 그때 다시 설명하겠다. 지금은 이 이벤트 핸들러가 UI 쓰레드와 다른 쓰레드에서 호출되기때문에 이 이탤릭체 부분의 코드가 필요하다는 것만 언급해두고 넘어가겠다.

볼드체로 되어 있는 부분에서는 먼저, ProgressBarVisibleChangedEvent 이벤트를 발생시킨 업무 화면 객체와 이벤트 인자를 통해서 넘겨준 인자를 구하고 있다.

ProgressBarVisibleChangedEvent 이벤트는 업무 화면 객체 Dalbong2ControlBase( 그리고 Dalbong2PageBase)에 구현되어 있다.

public class Dalbong2ControlBase : UserControl, IDalbong2Element, IProgresssBarPerceptible

{

    #region IDalbong2Element Members

    <중략>…

    #endregion

 

    #region IProgresssBarPerceptible Members

    public event ProgressBarVisibleChangedEventHandler ProgressBarVisibleChanged;

 

    private bool _CallingService = false;

    public bool WhileCallingService

    {

        get

        {

            return _CallingService;

        }

        set

        {

            _CallingService = value;

        }

    }

 

    private Visibility _ProgressBarVisibility = Visibility.Collapsed;

    public Visibility ProgressBarVisibility

    {

        get

        {

            return _ProgressBarVisibility;

        }

        set

        {

            if (_ProgressBarVisibility != value)

            {

                _ProgressBarVisibility = value;

                ProgressBarVisibleChangedEventArgs arg =

                    new ProgressBarVisibleChangedEventArgs(_ProgressBarVisibility);

                OnProgressBarVisibleChanged(arg);

            }

        }

    }

    #endregion

 

    protected virtual void OnProgressBarVisibleChanged(ProgressBarVisibleChangedEventArgs arg)

    {

        if (ProgressBarVisibleChanged != null)

        {

            ProgressBarVisibleChanged(this, arg);

        }

    }

}

ProgressVarVisibility 속성의 값을 설정할때 현재값과 다른 값이 들어오면 ProgressBarVisibleChanged 이벤트를 발생시킨다. 앞의 그림에서 본 것처럼 ProgressVarVisibility 속성은 BongServiceProxyFactory에서 설정한다.

ProgressBarVisibleChangedEvent 이벤트 발생시 추가적인 정보를 전달하기 위해서 다음과 같은 이벤트 인자를 정의하고 있다.

public delegate void ProgressBarVisibleChangedEventHandler( object sender,

ProgressBarVisibleChangedEventArgs arg );

public class ProgressBarVisibleChangedEventArgs

{

 

    private Visibility _Visibility = Visibility.Collapsed;

 

    public ProgressBarVisibleChangedEventArgs(Visibility visibility)

    {

        _Visibility = visibility;

    }

 

    public Visibility Visibility

    {

        get

        {

            return _Visibility;

        }

    }

}

이 이벤트 인자는 ProgressBarVisibleChangedEvent 발생시 현재 visible 상태를 전달하고 있다.

UI 컨테이너에서는 ProgressBarVisibleChangedEvent 이벤트를 발생시킨 업무 화면 객체가 현재 활성화되어 있는 업무 객체와 같은지를 우선 체크하고 그리고 이벤트 인자를 통해서 넘겨준 visible 상태를 통해서 프로그레스바 활성화를 결정하게 되는 것이다.

이것으로 달봉이가 구현해놓은 프로그레스바 자동 출력하기 구조 설명은 끝났다. 좀 복잡한 듯하다.

 

■ Dalbong2ProxyFactory vs. BongServiceProxyFactory

 

마지막으로 하나 더 언급할 것은 Dalbong2ProxyFactory와 BongServiceProxyFactory의 차이점이다.

첫번째로 Dalbong2ProxyFactory는 단지 서비스 시작과 종료를 알리는 이벤트만을 발생시킬 뿐이다. Dalbong2ProxyFactory에게는 UI단에서 어떤 컨트롤을 사용하고 어떤 애플리케이션에서 이 이벤트를 사용하는지는 중요하지 않다. 그래서 Dalbong2ProxyFactory를 다음처럼 Dalobg2.Win 프로젝트에 포함된 것이 아니라 Dalbong2.ServiceClient 프로젝트에 포함되어 있다.

 Dalbong2ProxyFactory

그러나 BongServiceProxyFactory는 서서히 UI단과 관계를 갖기 시작한다. 서비스 프락시 객체를 생성할때  IProgresssBarPerceptible 인자를 받는데 이 녀석은 업무 화면 객체가 구현하고 있는 인터페이스이다. 따라서 BongServiceProxyFactory는 Bong.Win 프로젝트에 구현되어 있다.

  BongServiceProxyFactory

프로그레스바의 자동 출력을 원하는 개발자는 BongServiceProxyFactory 객체를 사용해서 프락시 객체를 이용해야 하는 것이다.

 

■ 실행결과

 

이제 이 기능을 이용해서 구현된 프로그레스바 출력 기능이 어떻게 나타나는지를 보자.

 화면1

 화면2

업무 화면 1과 업무 화면 2는 같은 서버측 메소드를 호출하고 있다. 각각의 버튼을 클릭해서 서비스를 호출해서 서버측에서 서비스를 처리중이더라도 탭 전환이 가능하다. 또한 탭 전환이 이뤄질때 각 화면의 상태에 따라서 상태바에 있는 프로그레스바의 출력 여부가 결정된다.

이것으로 끝이다.

그럼 다음 포스트에서는 BongServiceProxyFactory 객체를 이용해서 서비스를 호출하는 코드를 작성해본다.

Posted by dalbong2