Udostępnij za pośrednictwem


Sekwencja inicjowania podtypów projektów

Środowisko konstruuje projekt przez wywołanie podstawowej implementacji CreateProjectfabryki projektu . Konstrukcja podtypu projektu rozpoczyna się, gdy środowisko określa, że lista identyfikatorów GUID typu projektu dla rozszerzenia pliku projektu nie jest pusta. Rozszerzenie pliku projektu i identyfikator GUID projektu określają, czy projekt jest typem projektu Visual Basic, czy Visual C#. Na przykład rozszerzenie vbproj i {F184B08F-C81C-45F6-A57F-5ABD99991F28F} identyfikują projekt języka Visual Basic.

Inicjowanie podtypów projektu w środowisku

Poniższa procedura zawiera szczegóły sekwencji inicjowania systemu projektu zagregowanego przez wiele podtypów projektu.

  1. Środowisko wywołuje element projektu CreateProjectpodstawowego , a projekt analizuje jego plik projektu, odnajduje, że lista identyfikatorów GUID typu projektu agregacji nie nulljest . Projekt kończy bezpośrednie tworzenie projektu.

  2. Projekt wywołuje usługę QueryService SVsCreateAggregateProject w celu utworzenia podtypu projektu przy użyciu implementacji CreateAggregateProject środowiska metody . W ramach tej metody środowisko wykonuje cykliczne wywołania funkcji do implementacji PreCreateForOuterSetInnerProject metod i InitializeForOuter podczas przechodzenia przez listę identyfikatorów GUID typu projektu, począwszy od najbardziej zewnętrznego podtypu projektu.

    Poniżej przedstawiono szczegółowe instrukcje inicjowania.

    1. Implementacja CreateAggregateProject środowiska metody wywołuje metodę HrCreateInnerProj za pomocą następującej deklaracji funkcji:

      <CodeContentPlaceHolder>0

      Gdy ta funkcja jest wywoływana po raz pierwszy, oznacza to, że w przypadku najbardziej zewnętrznego podtypu projektu parametry pOuter i pOwner są przekazywane jako null , a funkcja ustawia najbardziej zewnętrzny podtyp IUnknown projektu na pOuterwartość .

    2. Następnie środowisko wywołuje HrCreateInnerProj funkcję z drugim identyfikatorem GUID typu projektu na liście. Ten identyfikator GUID odpowiada drugiemu podtypowi projektu wewnętrznego krok po kroku w kierunku projektu podstawowego w sekwencji agregacji.

    3. Element pOuter wskazuje IUnknown teraz na podtyp najbardziej zewnętrznego projektu i HrCreateInnerProj wywołuje implementację PreCreateForOuter , po której następuje wywołanie implementacji SetInnerProjectelementu . W PreCreateForOuter metodzie przekazujesz kontrolę IUnknown najbardziej zewnętrznego podtypu projektu, pOuter. Należący do niego projekt (podtyp projektu wewnętrznego) musi utworzyć tutaj zagregowany obiekt projektu. W implementacji SetInnerProject metody przekazujesz wskaźnik do IUnknown projektu wewnętrznego, który jest agregowany. Te dwie metody tworzą obiekt agregacji, a implementacje muszą być zgodne z regułami agregacji COM, aby upewnić się, że podtyp projektu nie zawiera liczby odwołań do siebie.

    4. HrCreateInnerProjwywołuje implementację .PreCreateForOuter W tej metodzie podtyp projektu wykonuje swoją pracę inicjaliza. Możesz na przykład zarejestrować zdarzenia rozwiązania w programie InitializeForOuter.

    5. HrCreateInnerProj jest wywoływana rekursywnie do momentu osiągnięcia ostatniego identyfikatora GUID (projektu podstawowego) na liście. Dla każdego z tych wywołań kroki, c przez d, są powtarzane. pOuter wskazuje najbardziej zewnętrzny podtyp IUnknown projektu dla każdego poziomu agregacji.

Przykład

W poniższym przykładzie szczegółowo przedstawiono proces programowy w przybliżonej reprezentacji CreateAggregateProject metody, która jest implementowana przez środowisko. Kod jest tylko przykładem; nie jest przeznaczony do skompilowania, a wszystkie sprawdzanie błędów zostało usunięte w celu zapewnienia przejrzystości.

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);
}