개발 환경이 제대로 구성되었는지를 확인하면서 가장 기본 웹 파트를 생성해서 배포하는 방법을 알아보도록 하겠습니다.

 

1.     SharePoint 프로젝트 템플릿 중에서 맨 위의 Empty SharePoint Project를 선택하고 Name Hello 로 입력 합니다.



위와 같은 프로젝트 템플릿은 SharePoint 2010 없이 Visual Studio 2010 만 설치해도 볼 수 있지만 SharePoint 개발 환경 위에서가 아니면 아래와 같은 메시지를 볼 수 있습니다.



2.     SharePoint 사이트를 입력하고 “Deploy as a farm solution” 을 선택합니다.


3.     잠시 후 Solution Explorer를 확인할 수 있으며 빈 솔루션이므로 새 항목 추가에서 Web Part를 선택하고 이름은 “HJ” 라고 입력 합니다.


4.     생성된 웹 파트에 대한 Solution Explorer 모습은 아래 그림과 같습니다.


5. 이제 코드 창에서 간단한 코드를 작성해봅니다
HJ.cs
코드에 이미 생성되어 있는 CreateChildControls 메서드에 아래와 같은 코드를 입력합니다.   단순 Hello World 라는 글자를 표시해주는 코드 입니다.


6.     작성이 완료되었다면 Solution Explorer 에서 Hello를 오른쪽 클릭하여 배포(Deploy)를 선택합니다. 2번 단계에서 선택한 Farm Solution으로 배포됩니다.

 

7. 배포되었는지 확인하기 위해 SharePoint 사이트를 열어 웹 파트를 추가해봅니다. 알고 계시다시피 SharePoint 2010 사이트는 리본으로 구성되어 있으며 사이트의 첫 페이지에서 Page 탭에서 Edit를 선택합니다. 그럼 아래 그림과 같이 Insert 탭에서 Web Part를 선택할 수 있습니다.


8.     Web Part 추가를 선택하면 별도 설정 하지 않았기 때문에 Custom HJ 라는 웹 파트를 아래 그림에서 확인할 수 있습니다. Add 를 선택해서 웹 파트를 추가합니다.



9.     이전 버전과 달리 웹 파트 영역에 대한 부분은 안보이고 기존 콘텐트 부분에 추가할 수 있습니다. Page 탭을 선택하고 Save 메뉴를 눌러 편집에서 빠져 나옵니다.

그럼 아래 그림과 같이 웹 파트가 추가되어 있는 것을 알 수 있습니다.



개발 환경이 완료되었는지 확인하기 위해 이번 버전과 유사하게 웹 파트를 생성하고 배포, 확인해보았습니다.

 

VS 2010 프로젝트 템플릿에서 보듯이 여러 템플릿을 이용해서 SharePoint 2010을 개발할 수 있습니다.


 

[JumpToDX11-9] Multi-threaded Rendering 을 위한 API.

DirectX 11 2010. 1. 11. 09:00 Posted by 알 수 없는 사용자



이번 시간에는 Multi-threaded Rendering 을 위한 API 들에 대해서 살펴보겠습니다.
기능 위주의 설명을 위해서 인자들에 대한 명시는 생략했습니다.
이점 주의해주시기 바랍니다.

ID3D11Device::CreateDeferredContext()

가장 먼저 살펴볼 것은 DeferredContext 의 생성입니다.
DeferredContext 는 스레드당 하나씩 생성되어질 수 있음을 앞선 시간을 통해서 언급했습니다.
또한 이 DeferredContext 는 Command List 들을 생성해서 가지고 있습니다.
즉, 렌더링이 가능한 상태라는 것입니다.
그런 기능을 우리는 Device 인터페이스를 통해서 생성합니다.
이것은 역시 Free thread 한 작업이기 때문에 Device 인터페이스를 이용합니다.

하나의 DeferredContext 는 thread-safe 합니다.
즉, 스레드 상에서 DeferredContext 가 관련 Command 들을 기록하는 것은 안전한 작업입니다.

간단한 사용 방법은 아래와 같습니다.
ID3D11DeviceContext* pDeferredContext = NULL;
hr = g_pd3dDevice->CreateDeferredContext(0, &pDeferredContext);


ID3D11DeviceContext::FinishCommandList()

신기하게도 우리는 이 API 호출 한번으로 CommandList 들을 기록하고 생성할 수 있습니다.
API 이름이 Finish 여서 Start나 Begin 계열의 API 를 검색해 보았지만, 없었습니다.^^
각각의 DeferredContext 별로 호출되기 때문에 DeviceContext 의 멤버함수로 되어 있습니다.
앞선 시간을 통해서 DeviceContext 는 ImmeidateContext 와 DeferredContext 로
분리될 수 있다고 언급했었습니다.
두 Context 모두 ID3D11DeviceContext 인터페이스를 사용하기 때문에 오해의 소지가 약간 있습니다.
FinishCommandList 는 DeferredContext 를 위한 API 임을 유념하시기 바랍니다.

간단한 사용 방법은 다음과 같습니다.
ID3D11CommandList* pd3dCommandList = NULL;
hr = pDeferredContext->FinishCommandList( FALSE, &pd3dCommandList );


ID3D11DeviceContext::ExecuteCommandList()

이 API는 DeferredContext 에 의해서 생성된 CommandList 들을 실행합니다.
역시나 ID3D11DeviceContext 의 멤버함수이기 때문에 혼란스러울 수 있습니다.
과연 ImmediateContext 가 이 함수를 호출할까요? 아니면, DeferredContext 일까요?

지난 시간들을 통해서 우리는 실제로 Multi-threaded Rendering 이라는 것은
CommandList 생성을 Multi-thread 기반으로 하는 것이라고 언급했었습니다.
그 이후에 실제 그래픽 카드로의 전송은 하나의 스레드만 할 수 있다고 했었습니다.
바로 그 사실입니다.
이 함수는 ImmediateContext 에 의해서 호출됩니다.
즉, 이 API 는 그래픽 카드로 해당 CommandList 들을 전송하는 것입니다.

간단한 사용 방법은 아래와 같습니다.
g_pImmediateContext->ExecuteCommandList( g_pd3dCommandList, TRUE );


이상 3가지 API 에 대해서 살펴보았습니다.
믿기지 않으시겠지만(?)
Multi-threaded Rendering 작업은 이 세가지 API로 할 수 있습니다.
나머지는 스레드 생성과 제어를 위한 작업이 결합되어야 할 것입니다.
일반적인 스레드 프로그래밍과 관련된 내용이라 이곳에서는 배제를 했습니다.
현재 DirectX SDK Sample 에는 'MultithreadedRendering11' 라는 것이 있습니다.( 2009 August 버전 기준 )
이것과 관련된 소스가 있으니 참고해서 보시면 좋을 것 같습니다.

이상으로 Multi-threaded Rendering 의 기본 개념 설명을 마치고자 합니다.
이 부분과 관련된 내용은 앞으로 정리가 되는대로 추가하거나 수정이 되어질 수 있을 것입니다.
다음 시간부터는 DirectX11 의 다른 주제를 가지고 돌아오겠습니다.^^
 

Welcome to Dynamic C#(10) - Dynamic Returns Again.(2)

C# 2010. 1. 11. 09:00 Posted by 알 수 없는 사용자

- 살림살이 좀 나아시졌습니까.

날씨가 계속 춥네요. 난데없이 목이 부어서 지난 금요일에는 조퇴를 했습니다-_-. 다들 건강 조심하시구요. 날씨가 추워서 그런가 여기저기서 어려움을 호소하는 목소리가 들리는 거 같습니다. 다들 하시는 일 잘되고 살림살이 좀 나아지셨으면 좋겠네여!


- 이어서 이어서!

지난포스트에서 보셨던 예제를 다시한번 보시죠.

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

d.foo();
d.SomeProp = 10;
d[10] = 10;

c.Foo(d);
C.StaticMethod(d);
c.SomeProp = d;

지난 포스트에서는 위쪽 그룹에 대해서 다뤘었는데요, 이번 포스트에서는 위 두 그룹중에서 아래쪽 그룹에 대해서 설명드려 보겠습니다. 우선, 가장 간단한 부분부터 다뤄보려고 하는데요, 아래와 같은 코드가 있다고 가정해보죠.

public class C
{
    public void Foo(decimal x) { ... }
    public void Foo(string x) { ... }
    static void Main(string[] args)
    {
        C c = new C();
        dynamic d = 10;
        c.Foo(d);
    }
}

이 코드가 실행되면 어떤일이 벌어질까요? 직관적으로 생각해봤을때... 지역변수c의 타입이 C라는 걸 알 수 있으니깐, C의 오버로드 2개중에 하나가 실행될거라고 생각해볼 수 있습니다. 근데, d의 타입이 dynamic이라는 것도 위 소스코드에서 알 수 있는데요, 그렇다는 이야기는 d의 실제 타입은 런타임에서 알 수 있으므로 컴파일러는 어떤 오버로드를 호출해야 하는지 판단할 수가 없습니다.

그래서 이렇게 생각해볼 수 있습니다. 컴파일러는 호출가능한 후보군을 추출해서 집합을 만들고, 런타임에 실제로 오버로드 판별을 통해서 적합한 메서드를 호출한다고 말이죠. 위의 경우에는 d의 값이 10이므로, 아마도 호환이 안되는 string보다는 decimal을 인자로 받는 오버로드가 호출될거라고 예측해볼 수 있습니다. 그러면, 좀 더 구체적으로 이야기 해보면서 뭐가 예측이랑 다르게 돌아가는지에 대해서 이야기 해보죠.

public class C
{
    public void Foo(decimal x) { ... }
    public void Foo(string x) { ... }
    static void Main(string[] args)
    {
        C c = new D();
        dynamic d = 10;
        c.Foo(d);
    }
}

public class D : C
{
    public void Foo(int x) {...}
}


클래스 D를 C로 부터 상속했고, c를 D의 생성자로 생성한 게 차이점인데요. 그리고 런타임에 c의 타입은 D일텐고, D에는 C가 가진 모든 오버로드보다 더 이 경우에 적합한 int형 파라미터를 가진 Foo가 있습니다. 10은 int형으로 간주될테니, D의 Foo가 가장 적합한 선택이 되겠죠.

그런데, 결과는 어떨까요? 이 부분에 대해서 잘 아시는 분이나 코드를 작성하다가 이상한 점을 발견하신 분이라면 대답하실 수 있으실텐데요. 아래의 그림에서 확인을..


네. 분명히 오버로드가 총 3개여야 할텐데, 두개 밖에 안 나옵니다. 그래서 분명히 D의 Foo가 가장 좋은 선택임에도 불구하고 계속해서 C의 Foo(decimal x)가 호출이 됩니다. 하지만, c를 생성할때 "D c = new D();"나 "dynamic c = new D()"처럼 생성하면, D의 Foo(int x)가 호출이 됩니다. 왜 그럴까요?


- 내가 알면 이글 보고 있겠냐.

dynamic과 관련된 동적 바인딩을 설계할때, 최대한 동적바인딩이 기존의 컴파일러가 정적바인딩에서 하던 짓을 비슷하게 하게끔 유지했다고 합니다. 그래서 그 결과로 dynamic이라고 명시된 매개변수나 receiver가 아니라면, 컴파일타임에 확인할 수 있는 타입을 그 변수의 타입으로 간주한다고 합니다. 즉, 위의 예제에서 c.Foo의 오버로드로 D.Foo(int x)가 포함이 안된 이유는, "C c = new D();"의 결과로 c가 런타임에 가질 타입은 D겠지만, 컴파일타임에서는 C라고 간주한다는 겁니다. 그래서 아무리 인텔리센스를 뒤져봐도 D의 Foo를 발견할 수 없으며 호출도 할 수 없는 거죠.

하지만, "D c = new D();"나 "dynamic c = new D()"처럼 생성하면, 전자의 경우는 컴파일 타임의 c의 타입을 D로 간주하므로 오버로드 3개모두를 인텔리센스에서 확인하실 수 있구요, 후자의 경우는 동적 바인딩을 통해서 c의 런타임 타입이 D임을 알기때문에, 오버로드 후보군에서 Foo(int x)를 골라낼 수 있습니다. 예제를 하나 더 보면요.

public class C
{
    public void Foo(int x, object o)
    {
        Console.WriteLine("Foo(int x, object o)");
    }

    static void Main(string[] args)
    {
        C c = new D();
        dynamic d = 10;
        c.Foo(d, c);
    }
}

public class D : C
{
    public void Foo(int x, D d)
    {
        Console.WriteLine("int x, D d");
    }
}

위의 경우와 마찬가지로, C.Foo(int x, object o)가 호출됩니다. 같은 이유로 말이죠.


- 마치면서

사실 이번 포스트는 좀 애로사항이 있었는데요. 제 실력부족으로 참고했던 원문이 잘 이해가 안가서 말이죠. 그래서 제 나름대로 이런저런 실험을 해보다가 결론을 내렸습니다. 바로 이럴때가 고수님들의 나눔이 필요한 시점입니다. 혹시 더 자세하게 아시는 분이 있다면, 따쓰한 피드백으로 풍성하게 해주시기 바랍니다. "따쓰한" 잊지마세염^^;;;


-참고자료

1. http://blogs.msdn.com/samng/archive/2008/11/06/dynamic-in-c-iii-a-slight-twist.aspx