Compartilhar via


Sequência de inicialização de subtipos do projeto

O ambiente constrói um projeto chamando a implementação de fábrica de projeto base de CreateProject. A construção de um subtipo de projeto começa quando o ambiente determina que a lista GUID do tipo de projeto para a extensão de um arquivo de projeto não está vazia. A extensão de arquivo de projeto e o GUID do projeto especificam se o projeto é um tipo de projeto Visual Basic ou Visual C#. Por exemplo, a extensão .vbproj e {F184B08F-C81C-45F6-A57F-5ABD9991F28F} identificam um projeto do Visual Basic.

Inicialização de subtipos de projeto do ambiente

O procedimento a seguir detalha a sequência de inicialização de um sistema de projeto agregado por vários subtipos de projeto.

  1. O ambiente chama o projeto CreateProjectbase e, enquanto o projeto analisa seu arquivo de projeto, ele descobre que a lista de GUIDs do tipo de projeto agregado não nullé . O projeto interrompe a criação direta de seu projeto.

  2. O projeto chama QueryService o SVsCreateAggregateProject serviço para criar um subtipo de projeto usando a implementação do CreateAggregateProject método pelo ambiente. Dentro desse método, o ambiente faz chamadas de função recursiva para suas implementações e PreCreateForOuterSetInnerProjectInitializeForOuter métodos enquanto ele está percorrendo a lista de GUIDs do tipo de projeto, começando com o subtipo de projeto mais externo.

    O seguinte detalha as etapas de inicialização.

    1. A implementação CreateAggregateProject do método pelo ambiente chama o HrCreateInnerProj método com a seguinte declaração de função:

      <CodeContentPlaceHolder>0

      Quando essa função é chamada pela primeira vez, ou seja, para o subtipo de projeto mais externo, os parâmetros são passados pOuter como pOwner e a função define o subtipo null de projeto mais externo como IUnknown.pOuter

    2. Em seguida, o ambiente chama HrCreateInnerProj a função com o guid do segundo tipo de projeto na lista. Esse GUID corresponde ao segundo subtipo do projeto interno entrando em direção ao projeto base na sequência de agregação.

    3. O pOuter agora está apontando para o IUnknown subtipo de projeto mais externo e HrCreateInnerProj chama sua implementação de PreCreateForOuter seguido por uma chamada para sua implementação de SetInnerProject. No PreCreateForOuter método, você passa o controle IUnknown do subtipo de projeto mais externo. pOuter O projeto de propriedade (subtipo do projeto interno) precisa criar seu objeto de projeto agregado aqui. Na implementação do SetInnerProject método, você passa um ponteiro para o IUnknown projeto interno que está sendo agregado. Esses dois métodos criam o objeto de agregação e suas implementações precisam seguir as regras de agregação COM para garantir que um subtipo de projeto não acabe mantendo uma contagem de referência para si mesmo.

    4. HrCreateInnerProj chama sua implementação de PreCreateForOuter. Nesse método, o subtipo do projeto faz seu trabalho de inicialização. Você pode, por exemplo, registrar eventos de solução em InitializeForOuter.

    5. HrCreateInnerProj é chamado recursivamente até que o último GUID (o projeto base) na lista seja atingido. Para cada uma dessas chamadas, as etapas, c a d, são repetidas. pOuter aponta para o subtipo IUnknown de projeto mais externo para cada nível de agregação.

Exemplo

O exemplo a seguir detalha o processo programático em uma representação aproximada do CreateAggregateProject método conforme ele é implementado pelo ambiente. O código é apenas um exemplo; não se destina a ser compilado e toda a verificação de erros foi removida para maior clareza.

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