Partilhar via


Seqüência de inicialização de subtipos de projeto

O ambiente constrói um projeto chamando a implementação de fábrica do projeto base de CreateProject. A construção de um subtipo de projeto começa quando o ambiente determina que a lista GUID de tipo de projeto para a extensão de um arquivo de projeto não está vazia. A extensão do 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 dos subtipos de projeto pelo ambiente

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

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

  2. O projeto chama o serviço QueryServiceSVsCreateAggregateProject para criar um subtipo de projeto usando a implementação do método do ambiente CreateAggregateProject. Neste método, o ambiente faz chamadas de função recursivas para as suas implementações dos métodos PreCreateForOuter, SetInnerProject e InitializeForOuter, enquanto percorre a lista de GUIDs de tipos de projeto, começando com o subtipo de projeto mais externo primeiro.

    A seguir detalhamos as etapas de inicialização.

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

      <CodeContentPlaceHolder>0

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

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

    3. O pOuter agora está apontando para o IUnknown do subtipo de projeto mais exterior e o HrCreateInnerProj chama a sua implementação de PreCreateForOuter, seguida de uma chamada para a sua implementação de SetInnerProject. No método PreCreateForOuter, você passa o controle IUnknown do subtipo de projeto mais externo, pOuter. O projeto de propriedade (subtipo de projeto interno) precisa criar seu objeto de projeto agregado aqui. Na implementação do método SetInnerProject, passa-se um ponteiro para o IUnknown do projeto interno que está a ser agregado. Esses dois métodos criam o objeto de agregação e suas implementações precisam seguir 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 invoca a sua implementação de PreCreateForOuter. Nesse método, o subtipo de projeto faz seu trabalho de inicialização. Você pode, por exemplo, registrar eventos de solução no InitializeForOuter.

    5. HrCreateInnerProj é chamado recursivamente até que o último GUID (o projeto base) na lista seja alcançado. Para cada uma dessas chamadas, as etapas, de 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 à medida que 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);
}