프로젝트 하위 형식의 초기화 시퀀스
환경은 CreateProject의 기본 프로젝트 팩터리 구현을 호출하여 프로젝트를 생성합니다. 프로젝트 하위 형식의 생성은 프로젝트 파일 확장명의 프로젝트 형식 GUID 목록이 비어 있지 않다고 환경에서 판단할 때 시작됩니다. 프로젝트 파일 확장명과 프로젝트 GUID는 프로젝트가 Visual Basic인지 또는 Visual C# 프로젝트 형식인지 여부를 지정합니다. 예를 들어 .vbproj 확장명 및 {F184B08F-C81C-45F6-A57F-5ABD9991F28F}는 Visual Basic 프로젝트를 식별합니다.
환경의 프로젝트 하위 형식 초기화
다음 절차에서는 여러 프로젝트 하위 형식으로 집계된 프로젝트 시스템의 초기화 시퀀스를 자세히 설명합니다.
환경이 기본 프로젝트의 CreateProject를 호출하고 프로젝트가 프로젝트 파일을 구문 분석하는 동안, 집계 프로젝트 형식 GUID 목록은
null
이 아니라는 것을 발견합니다. 프로젝트가 직접 프로젝트 만들기를 중단합니다.프로젝트는 SVsCreateAggregateProject 서비스에서
QueryService
를 호출하여 환경의 CreateAggregateProject 메서드 구현을 사용하여 프로젝트 하위 형식을 만듭니다. 이 메서드 내에서 환경은 가장 바깥쪽 프로젝트 하위 형식부터 시작하여 프로젝트 형식 GUID 목록을 탐색하는 동안 PreCreateForOuter, SetInnerProject, InitializeForOuter 메서드의 사용자 구현에 대한 재귀 함수 호출을 수행합니다.다음은 초기화 단계에 대해 자세히 설명합니다.
환경의 CreateAggregateProject 메서드 구현은 다음 함수 선언을 사용하여
HrCreateInnerProj
메서드를 호출합니다.<CodeContentPlaceHolder>0
이 함수가 처음으로 호출될 때 즉 가장 바깥쪽 프로젝트 하위 형식의 경우에 매개 변수
pOuter
및pOwner
는null
로 전달되고 함수는 가장 바깥쪽 프로젝트 하위 형식IUnknown
을pOuter
로 설정합니다.다음으로 환경은 목록에 있는 두 번째 프로젝트 형식 GUID를 사용하여
HrCreateInnerProj
함수를 호출합니다. 이 GUID는 집계 시퀀스에서 기본 프로젝트를 향해 들어오는 두 번째 내부 프로젝트 하위 형식에 해당합니다.이제
pOuter
는 가장 바깥쪽 프로젝트 하위 형식의IUnknown
을 가리키고HrCreateInnerProj
는 PreCreateForOuter의 구현을 호출한 다음 SetInnerProject 구현을 호출합니다. PreCreateForOuter 메서드에서는 가장 바깥쪽 프로젝트 하위 형식인pOuter
의IUnknown
제어를 전달합니다. 소유 프로젝트(내부 프로젝트 하위 형식)는 여기에 집계 프로젝트 개체를 만들어야 합니다. SetInnerProject 메서드 구현에서는 집계되는 내부 프로젝트의IUnknown
에 대한 포인터를 전달합니다. 이러한 두 메서드는 집계 개체를 만들고, 구현에서는 COM 집계 규칙을 따라 프로젝트 하위 형식이 자체에 대한 참조 수를 보유하지 않도록 해야 합니다.HrCreateInnerProj
는 PreCreateForOuter의 구현을 호출합니다. 이 메서드에서 프로젝트 하위 형식은 초기화 작업을 수행합니다. 예를 들어 InitializeForOuter에서 솔루션 이벤트를 등록할 수 있습니다.HrCreateInnerProj
는 목록의 마지막 GUID(기본 프로젝트)에 도달할 때까지 재귀적으로 호출됩니다. 이러한 각 호출에 대해 c~d 단계가 반복됩니다.pOuter
는 각 집계 수준의 가장 바깥쪽 프로젝트 하위 형식IUnknown
을 가리킵니다.
예시
다음 예제에서는 환경에 의해 구현되는 CreateAggregateProject 메서드의 대략적인 표현으로 프로그래밍 프로세스를 자세히 설명합니다. 코드는 단지 예제일 뿐입니다. 컴파일하기 위한 것이 아니며 명확성을 위해 모든 오류 검사가 제거되었습니다.
HRESULT CreateAggregateProject
(
LPCOLESTR lpstrGuids,
LPCOLESTR pszFilename,
LPCOLESTR pszLocation,
LPCOLESTR pszName,
VSCREATEPROJFLAGS grfCreateFlags,
REFIID iidProject,
void **ppvProject)
{
HRESULT hr = NOERROR;
CComPtr<IUnknown> srpunkProj;
CComPtr<IVsAggregatableProject> srpAggProject;
CComBSTR bstrGuids = lpstrGuids;
BOOL fCanceled = FALSE;
*ppvProject = NULL;
HrCreateInnerProj(
bstrGuids, NULL, NULL, pszFilename, pszLocation,
pszName, grfCreateFlags, &srpunkProj, &fCanceled);
srpunkProj->QueryInterface(
IID_IVsAggregatableProject, (void **)&srpAggProject));
srpAggProject->OnAggregationComplete();
srpunkProj->QueryInterface(iidProject, ppvProject);
}
HRESULT HrCreateInnerProj
(
WCHAR *pwszGuids,
IUnknown *pOuter,
IVsAggregatableProject *pOwner,
LPCOLESTR pszFilename,
LPCOLESTR pszLocation,
LPCOLESTR pszName,
VSCREATEPROJFLAGS grfCreateFlags,
IUnknown **ppInner,
BOOL *pfCanceled
)
{
HRESULT hr = NOERROR;
CComPtr<IUnknown> srpInner;
CComPtr<IVsAggregatableProject> srpAggInner;
CComPtr<IVsProjectFactory> srpProjectFactory;
CComPtr<IVsAggregatableProjectFactory> srpAggPF;
GUID guid = GUID_NULL;
WCHAR *pwszNextGuids = wcschr(pwszGuids, L';');
WCHAR wszText[_MAX_PATH+150] = L"";
if (pwszNextGuids)
{
*pwszNextGuids++ = 0;
}
CLSIDFromString(pwszGuids, &guid);
GetProjectTypeMgr()->HrGetProjectFactoryOfGuid(
guid, &srpProjectFactory);
srpProjectFactory->QueryInterface(
IID_IVsAggregatableProjectFactory,
(void **)&srpAggPF);
srpAggPF->PreCreateForOuter(pOuter, &srpInner);
srpInner->QueryInterface(
IID_IVsAggregatableProject, (void **)&srpAggInner);
if (pOwner)
{
IfFailGo(pOwner->SetInnerProject(srpInner));
}
if (pwszNextGuids)
{
CComPtr<IUnknown> srpNextInner;
HrCreateInnerProj(
pwszNextGuids, pOuter ? pOuter : srpInner,
srpAggInner, pszFilename, pszLocation, pszName,
grfCreateFlags, &srpNextInner, pfCanceled);
}
return srpAggInner->InitializeForOuter(
pszFilename, pszLocation, pszName, grfCreateFlags,
IID_IUnknown, (void **)ppInner, pfCanceled);
}