Compilar um aplicativo WPF
Os aplicativos do Windows Presentation Foundation (WPF) podem ser criados como executáveis do .NET Framework (.exe), bibliotecas (.dll) ou uma combinação de ambos os tipos de assemblies. Este tópico apresenta como criar aplicativos WPF e descreve as principais etapas no processo de compilação.
Criando um aplicativo WPF
Um aplicativo WPF pode ser compilado das seguintes maneiras:
Linha de comando. O aplicativo deve conter apenas código (sem XAML) e um arquivo de definição de aplicativo. Para obter mais informações, consulte Construção pela Linha de Comando com csc.exe ou Construção a partir da Linha de Comando (Visual Basic).
Mecanismo de compilação da Microsoft (MSBuild). Além do código e dos arquivos XAML, o aplicativo deve conter um arquivo de projeto MSBuild. Para obter mais informações, consulte "MSBuild".
Visual Studio. Visual Studio é um ambiente de desenvolvimento integrado que compila aplicativos WPF com MSBuild e inclui um designer visual para criar interface do usuário. Para obter mais informações, consulte Escrever e gerenciar código usando o Visual Studio e Design XAML no Visual Studio.
Pipeline de construção do WPF
Quando um projeto WPF é criado, a combinação de destinos específicos do idioma e do WPF são invocados. O processo de execução desses alvos é chamado de pipeline de construção, e as principais etapas são ilustradas pela figura a seguir.
Inicializações antes da compilação
Antes de criar, o MSBuild determina a localização de ferramentas e bibliotecas importantes, incluindo o seguinte:
O .NET Framework.
Os diretórios do SDK do Windows.
A localização dos assemblies de referência do WPF.
A propriedade para os caminhos de pesquisa da assemblagem.
O primeiro local onde o MSBuild procura por assemblies é o diretório de assemblies de referência (%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\). Durante esta etapa, o processo de compilação também inicializa as várias propriedades e grupos de itens e executa qualquer trabalho de limpeza necessário.
Resolução de Referências
O processo de compilação localiza e vincula os assemblies necessários para criar o projeto de aplicativo. Esta lógica está contida na tarefa ResolveAssemblyReference
. Todos os assemblies declarados como Reference
no arquivo de projeto são fornecidos para a tarefa, juntamente com informações sobre os caminhos de pesquisa e metadados sobre assemblies já instalados no sistema. A tarefa procura assemblies e utiliza os metadados do assembly instalado para filtrar os principais assemblies WPF que não precisam ser exibidos nos manifestos de saída. Isso é feito para evitar informações redundantes nos manifestos ClickOnce. Por exemplo, como PresentationFramework.dll pode ser considerado representativo de um aplicativo criado no e para o WPF, e como todos os assemblies do WPF existem no mesmo local em todas as máquinas que têm o .NET Framework instalado, não há necessidade de incluir todas as informações sobre todos os assemblies de referência do .NET Framework nos manifestos.
"Compilação de Marcação—Primeira Passagem"
Nesta etapa, os arquivos XAML são analisados e compilados para que o tempo de execução não gaste tempo analisando XML e validando valores de propriedade. O arquivo XAML compilado é pré-tokenizado para que, em tempo de execução, carregá-lo seja muito mais rápido do que carregar um arquivo XAML.
Durante esta etapa, as seguintes atividades ocorrem para cada arquivo XAML que é um item de compilação Page
:
O arquivo XAML é analisado pelo compilador de marcação.
Uma representação compilada é criada para esse XAML e copiada para a pasta obj\Release.
Uma representação CodeDOM de uma nova classe parcial é criada e copiada para a pasta obj\Release.
Além disso, um arquivo de código específico do idioma é gerado para cada arquivo XAML. Por exemplo, para uma página Page1.xaml em um projeto Visual Basic, um Page1.g.vb é gerado; para uma página Page1.xaml em um projeto C#, um Page1.g.cs é gerado. O ".g" no nome do ficheiro indica que o ficheiro é um código gerado que tem uma declaração de classe parcial para o elemento de nível superior do ficheiro de markup (como Page
ou Window
). A classe é declarada com o modificador partial
em C# (Extends
no Visual Basic) para indicar que há outra declaração para a classe em outro lugar, geralmente no Page1.xaml.cs de arquivo code-behind.
A classe parcial se estende da classe base apropriada (como Page para uma página) e implementa a interface System.Windows.Markup.IComponentConnector. A interface IComponentConnector tem métodos para inicializar um componente e conectar nomes e eventos em elementos em seu conteúdo. Consequentemente, o arquivo de código gerado tem uma implementação de método como a seguinte:
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater =
new System.Uri(
"window1.xaml",
System.UriKind.RelativeOrAbsolute);
System.Windows.Application.LoadComponent(this, resourceLocater);
}
Public Sub InitializeComponent() _
If _contentLoaded Then
Return
End If
_contentLoaded = True
Dim resourceLocater As System.Uri = _
New System.Uri("mainwindow.xaml", System.UriKind.Relative)
System.Windows.Application.LoadComponent(Me, resourceLocater)
End Sub
Por predefinição, a compilação de marcação é executada no mesmo contexto AppDomain que o motor MSBuild. Isso proporciona ganhos de desempenho significativos. Esse comportamento pode ser alternado com a propriedade AlwaysCompileMarkupFilesInSeparateDomain
. Isso tem a vantagem de descarregar todos os conjuntos de referência ao descarregar o AppDomainseparado.
Compilação de Linguagem de Marcação—Passagem 2
Nem todas as páginas XAML são compiladas durante a fase 1 da compilação de marcação. Os arquivos XAML que têm referências de tipo definidas localmente (referências a tipos definidos em código em outro lugar no mesmo projeto) estão isentos de compilação no momento. Isso ocorre porque esses tipos definidos localmente existem apenas na fonte e ainda não foram compilados. Para determinar isso, o analisador usa heurísticas que envolvem a procura de itens como x:Name
no arquivo de marcação. Quando tal instância é encontrada, a compilação desse arquivo de marcação é adiada até que os arquivos de código tenham sido compilados, após o que, a segunda passagem de compilação de marcação processa esses arquivos.
Classificação de arquivos
O processo de compilação coloca os arquivos de saída em diferentes grupos de recursos com base em qual assembly de aplicativo eles serão colocados. Em um aplicativo não localizado típico, todos os arquivos de dados marcados como Resource
são colocados no assembly principal (executável ou biblioteca). Quando UICulture
está definido no projeto, todos os arquivos XAML compilados e os recursos marcados especificamente como dependentes do idioma são colocados na assemblagem de recursos satélite. Além disso, todos os recursos neutros em termos de linguagem são colocados na assemblagem principal. Nesta etapa do processo de construção, essa determinação é feita.
As ações de compilação ApplicationDefinition
, Page
e Resource
no arquivo de projeto podem ser aumentadas com os metadados Localizable
(os valores aceitáveis são true
e false
), que ditam se o arquivo é específico do idioma ou neutro do idioma.
Compilação principal
A etapa de compilação principal envolve a compilação de arquivos de código. Isso é orquestrado pela lógica nos ficheiros de destino específicos do idioma Microsoft.CSharp.targets e Microsoft.VisualBasic.targets. Se as heurísticas determinarem que uma única passagem do compilador de marcação é suficiente, então a assembly principal é gerada. No entanto, se um ou mais arquivos XAML no projeto tiverem referências a tipos definidos localmente, um arquivo de .dll temporário será gerado para que os assemblies finais do aplicativo possam ser criados após a conclusão da segunda passagem da compilação de marcação.
Geração de manifesto
No final do processo de construção, depois de todos os assemblies da aplicação e ficheiros de conteúdo estarem prontos, são gerados os manifestos ClickOnce para a aplicação.
O arquivo de manifesto de implantação descreve o modelo de implantação: a versão atual, o comportamento de atualização e a identidade do editor, juntamente com a assinatura digital. Este manifesto destina-se a ser criado por administradores que lidam com a implantação. A extensão do arquivo é .xbap (para aplicativos de navegador XAML (XBAPs)) e .application para aplicativos instalados. O primeiro é ditado pela propriedade do projeto HostInBrowser
e, como resultado, o manifesto identifica a aplicação como hospedada no navegador.
O manifesto do aplicativo (um arquivo .manifest .exe) descreve os assemblies do aplicativo e as bibliotecas dependentes e lista as permissões exigidas pelo aplicativo. Este ficheiro destina-se a ser criado pelo programador da aplicação. Para iniciar um aplicativo ClickOnce, um usuário abre o arquivo de manifesto de implantação do aplicativo.
Esses ficheiros de manifesto são sempre criados para XBAPs. Para aplicativos instalados, eles não são criados, a menos que a propriedade GenerateManifests
seja especificada no arquivo de projeto com valor true
.
Os XBAPs obtêm duas permissões adicionais além das permissões atribuídas a aplicativos típicos da zona da Internet: WebBrowserPermission e MediaPermission. O sistema de compilação do WPF declara essas permissões no manifesto do aplicativo.
Suporte incremental à compilação
O sistema de compilação WPF fornece suporte para compilações incrementais. É bastante inteligente na deteção de alterações feitas na marcação ou no código, e compila apenas os artefatos afetados pela alteração. O mecanismo de compilação incremental usa os seguintes arquivos:
Um arquivo $(AssemblyName)_MarkupCompiler.Cache para manter o estado atual do compilador.
Um arquivo $(AssemblyName)_MarkupCompiler.lref para armazenar em cache os arquivos XAML com referências a tipos definidos localmente.
A seguir está um conjunto de regras que regem a compilação incremental:
O arquivo é a menor unidade na qual o sistema de compilação deteta alterações. Portanto, para um arquivo de código, o sistema de compilação não pode dizer se um tipo foi alterado ou se o código foi adicionado. O mesmo vale para arquivos de projeto.
O mecanismo de compilação incremental deve estar ciente de que uma página XAML define uma classe ou usa outras classes.
Se as entradas
Reference
forem alteradas, recompile todas as páginas.Se um arquivo de código for alterado, recompile todas as páginas com referências de tipo definidas localmente.
Se um arquivo XAML for alterado:
Se XAML for declarado como
Page
no projeto: se o XAML não tiver referências de tipo definidas localmente, recompile esse XAML mais todas as páginas XAML com referências locais; se o XAML tiver referências locais, recompile todas as páginas XAML com referências locais.Se XAML for declarado como
ApplicationDefinition
no projeto: recompile todas as páginas XAML (motivo: cada XAML tem referência a um tipo de Application que pode ter sido alterado).
Se o arquivo de projeto declarar um arquivo de código como definição de aplicativo em vez de um arquivo XAML:
Verifique se o valor
ApplicationClassName
no arquivo de projeto foi alterado (existe um novo tipo de aplicativo?). Em caso afirmativo, recompile todo o aplicativo.Caso contrário, recompile todas as páginas XAML com referências locais.
Se um arquivo de projeto for alterado: aplique todas as regras anteriores e veja o que precisa ser recompilado. As alterações nas seguintes propriedades acionam uma recompilação completa:
AssemblyName
,IntermediateOutputPath
,RootNamespace
eHostInBrowser
.
Os seguintes cenários de recompilação são possíveis:
Todo o aplicativo é recompilado.
Somente os arquivos XAML que têm referências de tipo definidas localmente são recompilados.
Nada é recompilado (se nada no projeto tiver mudado).
Ver também
.NET Desktop feedback