Visual Studio 2010 공식 팀 블로그 @vsts2010

Posted by 종혁

안녕하세요 박종혁입니다. 연말, 연초라고 너무 오래 쉬었군요. ㅠㅠ
새해복많이 받으세요~
 http://www.asp.net/learn/whitepapers/aspnet40/  사이트를 번역 세번째 시간입니다.

ASP.NET 1.0 릴리즈 이후 , 웹폼은 ASP.NET에서 핵심적인 특징을 가졌습니다. 다음을 포함하면서, ASP.NET 4는 많이 향상되었습니다.

  • 메타 태그를 설정하는 능력.
  • 뷰 스테이트에 더 많은 컨트롤.
  • 브라우저의 능력을 사용하는 더 쉬운 방법들..
  • 웹폼들을 함께 라우팅 하는 ASP.NET 사용에 대한 지원.
  • 발생된 ID들에 더 많은 컨트롤.
  • 데이터 컨트롤들 안에서 선택된 열들을 지속하는 능력.
  • FormView  와 FormView 컨트롤들에서 랜더링된 HTML에 더 많은 컨트롤.
  • 데이터 소스 컨트롤들을 위한 필터링된 지원.

Setting Meta Tags with the Page.MetaKeywords and Page.MetaDescription Properties

  ASP.NET 4 Web Forms에서 작은 추가가 이었는데, 그것은 Page 클래스의 두 속성 MetaKeywordsMetaDescription 입니다. 이 두 속성들은 당신의 페이지 안에 부합하는 메타 태그를 다시 표현했습니다. 다음 예를 보세요.

<head id="Head1" runat="server">
  <title>Untitled Page</title>
  <meta name="keywords" content="These, are, my, keywords" />
  <meta name="description" content="This is the description of my page" />
</head>

이 두 속성들은 페이지의 Title 속성이 하던 것과 같은 방법으로 작동합니다. 그것들은 이 두 가지 규칙을 따릅니다.

  1. 속성 네임을 대응하는 head  요소 안에 meta 태그들이 없다면(즉, Page.MetaKeywords 위하여 name="keywords" 이고 Page.MetaDescription 을 위하여 name="description" 이며, 이 속성들이 설정되지 않은 것을 의미합니다), meta 태그들은 그것이 랜더링 될 때, 그페이지에 추가 될 것입니다.
  2.  이 이름들과 함께 이미 meta 태그들이 있다면, 이 속성들은 존재하는 태그들의 내용을 위한 get과 set 매소드로 활동합니다.

  당신은 런타임에서 이 속성들을 설정할 수 있습니다. 그것은 당신이 DB 혹은 다른 소스로부터 내용을 얻게하며, 당신이 특정 페이지들을 위한 것을 설명하기 위하여 동적으로 그 태그들을 설정하게 합니다. 당신은 또한 웹폼 페이지 마크업 맨 위에 @ Page 지시어에서 KeywordsDescription 속성을 설정 할 수 있습니다. 다음 예를 보세요.

<%@ Page Language="C#" AutoEventWireup="true"
  CodeFile="Default.aspx.cs"
  Inherits="_Default"
  Keywords="These, are, my, keywords"
  Description="This is a description" %>

 이것은 페이지 내에서 이미 선언된 것이 있다면 meta 내용을 오버라이드 할 것입니다. 설명 meta 태그의 내용이 구글에서 향상된 검색 목록화 미리보기를 위하여 사용 됩니다. (부연 설명으로 구글 웹마스터 센트럴 블로그에서 Improve snippets with a meta description makeover 를 보세요) 구글과 윈도우 라이브 서치는 어떤 것을 위해서 키워드들의 내용을 사용하지 않습니다. 그러나 다른 검색 엔진은 가능 할 것입니다. 덧붙여 검색 엔진 가이드 웹사이트의 Meta Keywords Advice 를 보세요. 이 새로운 속성들은 간단한 특징입니다. 그러나 그것들은 당신이 이것들을 수동으로 추가할 필요가 있을 때 혹은  meta 태그를 만들기 위하여 당신 자신의 코드를 쓸 때 부담을 덜어 줄 것입니다.



Enabling View State for Individual Controls

  기본적으로 뷰 스테이트는 페이지에서 작동합니다. 결과적으로 페이지상의 각 컨트롤은 그것이 어플리케이션을 위해 필요하지 않다면 잠재적으로 뷰 스테이트를 저장합니다. 뷰 스테이트의 데이타는 페이지의 HTML 안에 포함되고, 클라이언트에게 페이지를 보내는데 걸리리는 시간을 증가시키고, 그것을 포스트 백합니다. 필요 이상으로 뷰 스테이트를 저장하는 것은 중요한 처리능력 감소의 원인이 될 수 있습니다. 초기 버전의 ASP.NET에서, 개발자들은 페이지 사이즈를 줄이기 위하여 개별적인 컨트롤들을 위한 뷰스테이트를 자제 할 수 있었습니다. 그러나 개별적 컨트롤들을 위하여 아주 명시적으로 해야했습니다. ASP.NET 4에서, 웹 서버 컨트롤들은 ViewStateMode 속성을 포함하였습니다. 그것은 당신이 기본적으로 뷰 스테이트를 자제하게 하였습니다. 그리고 페이지에서 그것을 필요로 하는 컨트롤들을 위해서만 그것을 사용하게 하였습니다. ViewStateMode 속성은 3가지 값을 취합니다: Enabled, Disabled, 그리고 InheritEnabled  그 컨트롤과 상속받거나 혹은 설정되지 않은 자식 컨트롤을 위하여 뷰 스테이트를 가능하게 하였고습니다. Disabled 은 뷰 스테이트를 사용하지 못하게 합니다. 그리고, Inherit 는 그 컨트롤이 부모 컨트롤로부터 설정하고 있는 ViewStateMode 를 사용하는 것을 구체화 시킵니다. 다음의 간단한 예는 ViewStateMode 속성이 어떻게 동작하는지 보여줍니다. 다음 페이지 안에 컨트롤들을 위한 마크업은 ViewStateMode 값을 포함합니다:

<form id="form1" runat="server">
  <script runat="server">
      protected override void OnLoad(EventArgs e) {
      if (!IsPostBack) {
        label1.Text = label2.Text = "[DynamicValue]";
      }
      base.OnLoad(e);
    }
  </script>
  <asp:PlaceHolder ID="PlaceHolder1" runat="server" ViewStateMode="Disabled">
      Disabled: <asp:Label ID="label1" runat="server" Text="[DeclaredValue]" /><br />
    <asp:PlaceHolder ID="PlaceHolder2" runat="server" ViewStateMode="Enabled">
        Enabled: <asp:Label ID="label2" runat="server" Text="[DeclaredValue]" />
    </asp:PlaceHolder>
  </asp:PlaceHolder>
  <hr />
  <asp:button ID="Button1" runat="server" Text="Postback" />
  <%-- Further markup here --%>

  당신이 보신 것처럼, 코드는 PlaceHolder1 컨트롤을 위한 뷰스테이트를 디스에이블 합니다. 자식 label1 컨트롤은 이 속성 값을 상속합니다.(Inherit 는 컨트롤의 ViewStateMode 를 위한 기본 값입니다.) 그리고 결과적으로 뷰스테이트를 저장하지 않습니다. PlaceHolder2 컨트롤에서 ViewStateModeEnabled 로 설정되고, 그 결과 label2 는 이 속성을 상속합니다. 그리고 뷰 스테이트를 저장합니다. 페이지가 처음 로드 될 때, 두 Label  컨트롤의 Text  속성은 문자열  "[DynamicValue]"로 설정됩니다. 이 설정들의 효과는 페이지가 처음 로드 할 때, 다음의 출력을 브라우저상에 보여줍니다.

Disabled: [DynamicValue]

Enabled:  [DynamicValue]

그러나 포스트백 후에 다음의 출력이 보여집니다:

Disabled: [DeclaredValue]

Enabled: [DynamicValue]

  아마도 당신이 예상하기로는, label1 (label1ViewStateMode 값은 Disabled 설정 됨)은 코드안에 설정된 값을 보존하지 않았습니다. 그러나, label2 (label2ViewStateMode 값은 Enabled 설정 됨)는 그것의 상태를 보존합니다. 당신은 또한 @ Page 지시어에서의 ViewStateMode 를 설정 할 수 있습니다. 다음 예를 보세요:

<%@ Page Language="C#" AutoEventWireup="true"
  CodeBehind="Default.aspx.cs"
  Inherits="WebApplication1._Default"
  ViewStateMode="Disabled" %>

  Page 클래스는 단지 다른 컨트롤이다; 그것은 페이지 상에서 다른 모든 컨트롤들의 부모 컨트롤로서 동작합니다. ViewStateMode 의 디폴트 값은 Page 객체를 위하여 Enabled 입니다. 왜냐하면 컨트롤들이 상속하기위하여 디폴트로 하기 때문에, 컨트롤들은 당신이 페이지 혹은 컨트롤 단계에서 ViewStateMode 를 설정하지 않더라도 Enabled 속성 값을 상속할 것입니다. ViewStateMode 속성 값은 EnableViewState 속성이 true로 설정되야만 뷰 스테이트가 유지될지 아닐지를  결정합니다. EnableViewState 속성이 false 로 설정이 되면, 뷰 스테이트는 ViewStateMode 가  Enabled 로 설정되어도 유지 되지 않을 것입니다. 이 특징을 살린 좋은 사례는 마스터 페이지안에 ContentPlaceHolder 컨트롤과 함께 사용하는 것입니다. 당신은 마스터 페이지를 위하여 ViewStateModeViewStateMode 로 설정 할 수 있습니다. 그런 다음에 ContentPlaceHolder 컨트롤을 위하여 그것을 개별적으로 인에이블 할 수 있습니다. 그ContentPlaceHolder 는 뷰스테이트가 필요한 컨트롤들을 차례로 포함합니다.

Changes to Browser Capabilities

  ASP.NET은 브라우저의 능력을 결정하는데, 사용자는 browser capabilities 라고 불리는 특징을 사용하는 것에 의하여 당신의 사아트를 탐색하는데 그것을 사용하고 있습니다. 브라우저 지원은 (Request.Browser  속성에 의하여 보여지는) HttpBrowserCapabilities 객체에 의하여 대표됩니다. 예를 들어, 당신은 현재 브라우저의 타입과 버전이 특별한 버전의 자바스크립트를 지원하는지를 알아내기 위하여 HttpBrowserCapabilities 객체를 사용할 수 있습니다. 혹은, 당신은 요청이 모바일 장치로부터 비롯된 것인지를 알아내기 위하여 HttpBrowserCapabilities 객체를 사용 할 수 있습니다. HttpBrowserCapabilities 객체는 한 세트의 브라우저 정의 파일들에 의해서 작동됩니다. 이 파일들은 특정 브라우저들의 지원에 대한 정보를 포함합니다. ASP.NET 4에서 이 브라우저 정의 파일들은 최근 소개된 브라우저들과 구글 크롬, Research in Motion 블랙베리 스파트폰들과 애플 아이폰 같은  장치들에 대한 정보를 포함하기 위하여 업데이트 됩니다.

  다음의 목록은 새로운 브라우저 정의 파일들입니다.

  • blackberry.browser
  • chrome.browser
  • Default.browser
  • firefox.browser
  • gateway.browser
  • generic.browser
  • ie.browser
  • iemobile.browser
  • iphone.browser
  • opera.browser
  • safari.browser



Using Browser Capabilities Providers

ASP.NET 3.5 서비스팩1에서, 당신은  다음의 방법들 중에서 지원을 정의 할 수 있습니다.

  • machine 레벨에서, 당신은 다음의 폴더 안에서 .browser XML 파일들을 만들거나 업데이트 할 수 있습니다.

\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers

  당신이 브라우저 지원을 정의한 후에, 당신은 Visual Studio Command Prompt로 부터 다음의 명령어를 실행합니다. 그것은 브라우저 지원 어셈블리를 재빌드하고 GAC(Global Assembly Cache)에 그것을 덧붙이기 위해서 입니다.

 aspnet_regbrowsers.exe -I c 
  • 개별적인 어플리케이션을 위하여, 당신은 어플리케이션의 Browsers 폴더 안에서 .browser 파일들을 만들 수 있습니다.

  이 접근들은 당신이 XML 파일들을 바꾸는데 필요하고, machine 레빌의 변화를 위해서 당신은 aspnet_regbrowsers.exe 프로세스를 돌린 후에, 어플리테이션을 재시작 해야 합니다. ASP.NET 4 는 브라우저 지원 공급자(rowser capabilities providers) 으로 관련된 특징을 포함합니다. 그 이름이 제안했을 때, 이것은 당신이 공급자를 빌드하게 합니다. 그 공급자는 순차적으로 당신이 브라우저 지원을 알아내기 위하여 당신의 코드를 사용하게 합니다. 실제로는, 개발자들이 종종 커스텀 브라우저 지원을 정의하지 않습니다. 브라우저 파일들은 업데이트하기 어려운데, 그 이유는 그것들을 업데이트를 위한 프로세스가 아주 복잡하기 때문입니다. 그리고 .browser 파일들을 위한 XML 문법은 사용하고 정의하기에 복잡할 것입니다.

  아주 초기에 이 프로세스를 만드는 것은 공통 브라우저 정의 문법이 혹은 최근의 브라우저 정의를 포함하는 데이터베이스 혹은 심지어 그러한 데이터베이스를 위한 웹서비스라고 할지라도 가능하였습니다. 새로운 브라우저 지원 공급자의 특징은 제 3의 개발자들을 위해서 가능하고 실제적인 이 시나리오들을 만듭니다. 새로운 ASP.NET 4 브라우저 지원 공급자 특징을 사용하시 위해서 두 가지의 주된 접근법이 있습니다: ASP.NET 4 브라우저 지원 정의 기능을 확장하기 위해서, 혹은 전체적으로 그것을 대체하는 것. 다음 절은 최초로 그 기능을 대체하는 법과 그 다음에 그것을 확장하는 법을 설명합니다.



Replacing the ASP.NET Browser Capabilities Functionality

 ASP.NET 브라우저 지원 정의 기능을 대체하기 위하여, 이 단계를 따라주세요:

1.   HttpCapabilitiesProvider 로 부터 상속한 공급자 클래스를 만듭니다. 그리고 다음의 예처럼 
GetBrowserCapabilities 매소드를 오버라이드하는 공급자 클래스를 만듭니다.       

public class CustomProvider : HttpCapabilitiesProvider { public override HttpBrowserCapabilities GetBrowserCapabilities(HttpRequest request) { HttpBrowserCapabilities browserCaps = new HttpBrowserCapabilities(); Hashtable values = new Hashtable(180, StringComparer.OrdinalIgnoreCase); values[String.Empty] = request.UserAgent; values["browser"] = "MyCustomBrowser"; browserCaps.Capabilities = values; return browserCaps; } }

이 예 안의 코드는 새로운 HttpBrowserCapabilities  객체를 만듭니다. 그것은 브라우저를 명명하는 지원을 상세화하고, MyCustomBrowser에 지원을 설정합니다.

     2.Register the provider with the application. 어플리케이션과 함께 공급자를 등록합니다.

  어플리케이션과 함께 공급자를 사용하기 위하여, 당신은 Web.config 혹은 Machine.config 파일 안의 browserCaps 섹션에 provider 특성을 덧붙여야 합니다. (특정 모바일 장치를 위한 폴더 처럼, 당신도 어플리케이션 안의 특별한 디렉토리들을 위하여  location  요소 안의 공급자 속성을 정의 할 수 있습니다. ) 다음의 예는 구성 파일안의 provider 속성을 설정하는 법을 보여줍니다.

<system.web> <browserCaps provider="ClassLibrary2.CustomProvider, ClassLibrary2, Version=1.0.0.0, Culture=neutral" /> </system.web>

 
새로운 브라우저 지원 정의를 등록하는 다른 방법은 코드를 사용하는 것인데, 다음 예를 보세요. 

void Application_Start(object sender, EventArgs e) { HttpCapabilitiesBase.BrowserCapabilitiesProvider = new ClassLibrary2.CustomProvider(); // ... }

  
  이 코드는 Global.asax 파일의 Application_Start 이벤트 안에서 동작합니다. 캐쉬가 결정된 HttpCapabilitiesBase 객체를 위한 유효한 상태로 남기위해서, BrowserCapabilitiesProvider 클래스에서 변화는 어플리케이션 실행 중 코드 전에 일어나야합니다. 
 









크리에이티브 커먼즈 라이선스
Creative Commons License

댓글을 달아 주세요

Posted by 강보람(워너비)

- 정말 오랜만에 다시 Dynamic이군요.

안녕하세요~! 눈 때문에, 어떤 사람들은 로맨틱한 겨울이고, 어떤 사람들은 악마의 똥가루의 냄새에 신음하고, 어떤 사람들은 방에 콕처박혀 있고 뭐 아주 버라이어티한 겨울입니다. 겨울이 버라이어티 정신이 충만하네요. 연예대상같은거라도 하나 받고 싶은 가봐요. ㅋㅋ 아무튼! 정말 오랜만에 다시 dynamic시리즈를 쓰게 되네요. 워낙 한 내용도 없이 중간에 끊어서 좀 그랬습니다;;; 물론, 기다리신 분이 얼마나 있을지는 미지수지만요-_- 그럼. 한번 이야기를 시작해볼까요? dynamic에 대해서 조금씩 자세하게 들어가 보겠습니다.


- 어서내놔 dynamic

우선 예제를 하나 보시죠.

dynamic d = 10;
C c = new C();

//위쪽 그룹 
d.foo();
d.SomeProp = 10;
d[10] = 10;

//아래쪽 그룹 
c.Foo(d);
C.StaticMethod(d);
c.SomeProp = d;




위 그룹과 아래 그룹의 차이점은 뭘까요? 네~! Give that man a cigar!(누가 정답을 말했을때 하는 말이라네요) 위 그룹은 액션을 받는 객체가 동적인 객체, 즉 dynamic receiver이구요. 아래 그룹은 static receiver와 static method가 바로 차이점입니다.

위 그룹은 동적인 표현식(expression)속에서 직접적으로 동적인 행위가 일어나고, 아래그룹은 직접적으로  동적표현식은 아닙니다. 각각의 연산의 매개변수로 동적인 타입이 들어가면서, 전체적인 표현식을 간접적으로 동적으로 만들고 있는거죠. 이런 경우에는 컴파일러가 동적인 바인딩과 정적인 바인딩을 섞어서 수행하는데요. 예를 들어서 동적타입을 매개변수로 받는 오버로드가 있을 경우에, 어떤 멤버집합(member set)을 오버로드해야 할지 결정할때는 정적인 타입을 사용해서 판단할테구요, 실제로 오버로드를 판별(resolution)할때는 매개변수의 런타임 타입을 사용할 것이기 때문이죠.

컴파일러가 dynamic타입인 표현식을 보게되면, 그 안에 포함된 연산들을 동적 연산처럼 처리하게 됩니다. 즉, 표현식이 인덱스를 통한 접근이든 메서드호출이든 상관없이 그 표현식의 결과로 나오는 타입은 런타임에 결정될거라는 거죠. 그 결과로 컴파일 타임에 동적인 표현식의 결과로 나오는 타입은 dynamic이겠죠.

컴파일러는 이런 모든 동적인 연산들을 DLR을 통해서 dynamic call site라는 걸로 변환을 합니다. 지지지난 포스트에서 설명을 드렸던거 같은데요, 제네릭한 델리게이트를 가지고 있는 정적 필드입니다. 어떤 연산에 대한 호출을 가지고 있다가, 추후에 같은 타입의 연산이 호출되면 다시 call site를 생성할 필요없이 정적필드에 저장된 델리게이트를 호출해서 실행에 필요한 부하를 최대한 줄이는데 도움을 주는 친구죠. call site가 만들어지면, 컴파일러는 그 call site에 저장된 델리게이트를 호출할 코드를 생성하구요, 거기에다가 매개변수를 넘겨줍니다.

만약에, 호출한 객체가 IDynamicObject를 구현해서 스스로 동적 연산을 어떻게 처리할지 아는 객체가 아니거나, 미리 저장된 델리게이트와 타입이 안맞아서 캐시가 불발이 나면, call site와 같이 생성된 CallSiteBinder가 호출됩니다. CallSiteBinder는 call site에 필요한 바인딩을 어떻게 처리해야 하는지 알고 있는 객체인데요, C#은 이 CallSiteBinder에서 상속한 바인더를 갖고 있습니다. 이 C# CallSiteBinder가 적절한 바인딩을 통해서 DLR의 call site가 갖고 있는 델리게이트에 저장될 내용을 expression tree형태로 만들어서 리턴합니다. 이 내용역시 전전, 전포스트에서 다뤘었쬬? 못봤다고 하시면!!!! 제가 절대 가만있을수는 없는 문제고! 링크를 드..드리겠습니다. 전포스트, 전전포스트. 친절하죠?-_-


- 캐시되는 과정은 어떠냥

공개된 문서를 통해 볼 수 있는 현재의 캐시 방식은 그냥 단순히 매개변수들의 타입이 일치하는지 검사하는겁니다.  만약에.. 이런 호출이 있다고 할때...

args0.M(arg1, arg2, ...);

그리고, 이전에 args0이 C라는 타입이며, 매개변수 arg1과 arg2가 모두 int인 호출이 있었다고 해보면요, 캐시를 체크하는 코드는 대략아래와 같습니다.

if (args0.GetType() == typeof(C) &&
    arg1.GetType() == typeof(int) &&
    arg2.GetType() == typeof(int) &&
    ...
    )
{
    //CallSiteBinder의 바인드 결과는 여기에 계속 통합되구요
}
    ......//캐시 검사는 좀 더 많을 수도 있구요
else
{
    //여기서 CallSiteBinder의 bind메서드를 호출하고, 캐시를 업데이트 합니다.
}

지금까지 간단하게 알아본 내용을 그래도 마무리 하려면, C# CallSiteBinder가 뭘 어떻게 하는지를 알면 되겠네요. 서두에 두그룹의 연산중에 위 그룹의 연산을 보면요, 메서드 호출, 속성 접근, 인덱서 호출등 3가지 연산이 있었죠. 일단 모든 연산은요 표준 C# runtime binder를 통해서 생성되고, C# runtime binder가 걔네들을 데이터 객체로 사용합니다. 그 데이터객체는 바운드되야할 액션을 설명하는데요, 그런 객체를 C# payload라고 부른다고 합니다. 

C# runtime binder는 쉽게 작은 컴파일러라고 생각하면 되는데요, 얘가 일반적인 컴파일러가 갖고 있는 심볼테이블이나 타입시스템, 오버로드 판별 및 타입 교체같은 기능을 갖고 있기 때문입니다. 간단하게 d.Foo(1)을 예로 생각해보죠.

runtime binder가 호출되면, 현재 call site에 대한 payload과 call site에 대한 런타임 매개변수를 갖습니다. 그리고 dynamic receiver를 포함해서 그 모든 런타임 매개변수와 타입을 모아서는 그 타입에 대한 심볼테이블을 만듭니다.(심볼테이블에 대한 간략한 설명은 여기를 참조하세영!) 그리곤 payload꾸러미를 풀어헤쳐서 수행하려고 하는 연산의 이름을 꺼냅니다.(Foo) 그리고 d의 타입에서 리플렉션을 사용해서 Foo라는 이름을 갖는 모든 멤버를 뽑아냅니다. 그리고 걔네들도 심볼테이블에 적어넣죠. 말로 설명하니깐 깝깝하시죠? 설명하는 저도 깝깝하네여-_-;;; 제가 상상력을 동원해서 부연설명을 드리면요,

d.Foo(1)에서 먼저 매개변수의 타입과 d의 타입을 갖고와서 심볼테이블에 적어두고요.

주소     타입            이름
서울시   int             익명(= 1)

수원시   dynamic      d

그리고 리플렉션으로 d의 타입에서 Foo를 모두 찾아냈는데 대략 아래와 같다고 해보죠.
Foo(int a)
Foo(double b)
Foo(string c)

그리고 얘네들도 따로 심볼테이블에 집어넣으면?

-call site에 대한 심볼테이블
주소     타입            이름
서울시   int            익명(= 1)
수원시   dynamic      d

-d의 멤버중에 Foo라는 동명이인들
주소      타입        이름
부산시   void     Foo(int a)
창원시   void     Foo(double b)
안양시   void     Foo(string c)

그러면, 타입을 찬찬히 들여다보면, 어떤 Foo가 호출되야 할지 명확하게 보입니다. d.Foo(1)호출에서 매개변수의 런타임타입이 int이므로 Foo(int a)가 호출이 되겠죠. 이건 그냥 제가 설명을 위해서 상상력을 동원해본거니깐요 믿지는 마시기 바랍니다. 예비군 동원 무쟈게 귀찮으시져? 상상력도 무쟈게 귀찮아 하네요-_-. 어서 집에 보내고 다시 설명을 이어 가겠습니다.

위에서 설명드린 runtime binder를 설계할때 세웠던 한가지 원칙은 "runtime binder는 정적 컴파일러가 하는 짓을 똑같은 의미로 할 수 있어야 한다."였다고 하는데요. 그래서 에러메세지 역시 동일한 에러메세지를 뱉어낸다고 합니다.

위의 바인딩의 결과로 바인딩이 성공적일 경우에 수행할 동작을 표현한 expression tree가 만들어집니다. 그렇게 안되는 경우에는 runtime binder exception을 던진다고 하네요. 결과로 만들어진 expression tree는 DLR의 캐시에 포함되고 호출되면서 원래의 호출을 성공적으로 완료합니다.


- 약간의 제약사항?

그런데, 위에서 정적 컴파일러와 똑같은 짓을 하게 만들려고 했지만, 아마도 예산과 시간때문에 선택과 집중을 해야 하니깐 몇가지 못집어 넣은게 있다고 합니다. 람다식과 확장 메서드, 메서드 그룹(델리게이트)에 대한 이야기 인데요. 현재로서는 바인딩 안된 람다식을 런타임에서 표현할 방법이 없다고 합니다. 개발하다가 디버깅을 할때 브레이크 포인트를 잡고 그 상태에서 현재 상태의 객체에 값을 가져온다거나 메서드를 호출하고 값을 확인할 수 있잖아요? 근데, 람다식은 그런식으로 디버깅이 안됐던거 같은데, 아마 그문제가 계속 이어지는 거 같습니다.

그리고 메서드 그룹역시 런타임에 표현할 수 있는 방법이 없다고 합니다. 예를 들면,

delegate void D();
public class C
{
     static void Main(string[] agrs)
     {
        dynamic d = 10;
        D del = d.Foo; //뭐 이렇게는 안된다고 하네요. 그래서 런타임 익셉션이 난다고 합니다.
     }
}

그리고 확장 메서드 역시 using절과 범위를 바인딩없이 넘겨줄 방법이 없기때문에, 확장메서드역시 안된다고 하구요.


- 마물!

무척 오랜만의 포스팅인데요, 갈증이 조금이라도 해소가 되셨으면 좋겠네요. 제 실력이 바닥을 기다보니 원문의 내용을 한번 걸러서 드리는 정도밖에 못드리는 면이 많은데요. 뭐-_- 내공이 부족하니 한계가 명확하네요. 그럼 다음 포스트에서 뵙져~!!!!!!!


- 참고자료

1. http://blogs.msdn.com/samng/archive/2008/11/02/dynamic-in-c-ii-basics.aspx


크리에이티브 커먼즈 라이선스
Creative Commons License

댓글을 달아 주세요