Compilazione di un'applicazione WPF (WPF)

Le applicazioni Windows Presentation Foundation (WPF) possono essere compilate come file eseguibili .NET Framework (.exe), librerie (.dll) o come combinazione dei due tipi di assembly. In questo argomento viene illustrato come compilare applicazioni WPF e vengono descritti i passaggi chiave del processo di compilazione.

Nel presente argomento sono contenute le seguenti sezioni.

  • Compilazione di un'applicazione WPF
  • Pipeline di compilazione WPF
  • Supporto per compilazioni incrementali
  • Argomenti correlati

Compilazione di un'applicazione WPF

È possibile compilare un'applicazione WPF nei modi seguenti:

Pipeline di compilazione WPF

Quando si compila un progetto WPF vengono richiamate tutte le destinazioni specifiche del linguaggio e di WPF. Il processo di esecuzione di queste destinazioni viene definito pipeline di compilazione. Nella figura che segue vengono illustrati i principali passaggi che costituiscono tale processo.

Processo di compilazione WPF

Inizializzazioni pre-compilazione

Prima della compilazione, MSBuild determina il percorso di strumenti e librerie importanti, tra cui:

  • Campo .NET Framework.

  • Le directory Windows SDK.

  • Il percorso degli assembly di riferimento WPF.

  • La proprietà per i percorsi di ricerca degli assembly.

Il primo percorso in cui MSBuild cerca gli assembly è la directory dell'assembly di riferimento (%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\). Durante questa fase, il processo di compilazione inizializza anche le varie proprietà e i gruppi di elementi ed esegue eventuali operazioni di pulitura necessarie.

Risoluzione dei riferimenti

Il processo di compilazione individua e associa gli assembly richiesti per compilare il progetto di applicazione. Questa logica è contenuta nell'attività ResolveAssemblyReference. Tutti gli assembly dichiarati come Reference nel file di progetto vengono forniti all'attività insieme alle informazioni sui percorsi di ricerca e ai metadati degli assembly già installati nel sistema. L'attività ricerca gli assembly e utilizza i metadati degli assembly installati per escludere gli assembly WPF di base che non devono essere visualizzati nei manifesti di output. In questo modo non vi saranno informazioni ridondanti nei manifesti ClickOnce. Ad esempio, dal momento che PresentationFramework.dll può essere considerato rappresentativo di un'applicazione compilata in e per WPF e tutti gli assembly WPF si trovano nello stesso percorso su ogni computer nel quale sia installato .NET Framework, non occorre includere tutte le informazioni su tutti gli assembly di riferimento .NET Framework nei manifesti.

Compilazione del markup – Passaggio 1

In questo passaggio i file XAML vengono analizzati e compilati, così che il runtime non dovrà analizzare XML né convalidare i valori delle proprietà. Il file XAML compilato viene presuddiviso in token, in modo tale da rendere molto più rapido il caricamento in fase di esecuzione.

Durante questo passaggio, per ogni file XAML che rappresenta un elemento di compilazione Page vengono eseguite le seguenti attività:

  1. Il file XAML viene analizzato dal compilatore di markup.

  2. Una rappresentazione compilata viene creata per il suddetto file XAML e copiata nella cartella obj\Release.

  3. Una rappresentazione CodeDOM di una nuova classe parziale viene creata e copiata nella cartella obj\Release.

Inoltre, viene generato un file di codice specifico del linguaggio per ogni file XAML. Ad esempio, per una pagina Page1.xaml in un progetto Visual Basic, viene generato un file Page1.g.vb. per una pagina Page1.xaml in un progetto C#, viene generato un file Page1.g.cs. Il componente ".g" nel nome del file indica la generazione di un file di codice avente una dichiarazione di classe parziale per l'elemento di primo livello del file di markup, quale ad esempio Page o Window. La classe viene dichiarata con il modificatore partial in C# e Extends in Visual Basic per indicare la presenza di un'altra dichiarazione di classe in un percorso diverso, generalmente nel file code-behind Page1.xaml.cs.

La classe parziale si estende dalla classe di base appropriata, ad esempio Page nel caso di una pagina, e implementa l'interfaccia System.Windows.Markup.IComponentConnector. L'interfaccia IComponentConnector possiede metodi che consentono di inizializzare un componente e connettere nomi ed eventi negli elementi del contenuto. Di conseguenza, l'implementazione dei metodi del file di codice generato sarà analoga alla seguente:

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

Per impostazione predefinita, la compilazione del markup viene eseguita nello stesso oggetto AppDomain del motore MSBuild. In questo modo si ottengono notevoli miglioramenti delle prestazioni. Questo comportamento può essere modificato mediante la proprietà AlwaysCompileMarkupFilesInSeparateDomain. Tale proprietà offre il vantaggio di scaricare tutti gli assembly di riferimento scaricando l'oggetto AppDomain separato.

Compilazione del markup – Passaggio 2

Non tutte le pagine XAML vengono compilate durante il passaggio 1 della compilazione del markup. I file XAML con riferimenti a tipi definiti localmente, ossia definiti altrove nel codice all'interno dello stesso progetto, non vengono compilati durante questa fase. Questo avviene perché i tipi definiti localmente esistono soltanto nell'origine e non sono ancora stati compilati. Per determinare quanto detto il parser utilizza un'euristica che implica la ricerca di elementi, ad esempio x:Name, nel file di markup. Quando un'istanza di questo tipo viene trovata, la compilazione del file di markup viene posticipata fino all'avvenuta compilazione dei file di codice, i quali verranno successivamente elaborati nel secondo passaggio di compilazione del markup.

Classificazione dei file

Durante il processo di compilazione i file di output vengono inseriti in gruppi di risorse diversi, a seconda dell'assembly dell'applicazione in cui verranno collocati. In un'applicazione non localizzata tipica, tutti i file di dati contrassegnati come Resource vengono collocati nell'assembly principale (eseguibile o libreria). Quando si imposta UICulture nel progetto, tutti i file XAML compilati e le risorse specificatamente contrassegnate come specifiche della lingua vengono collocati nell'assembly di risorse satellite. Inoltre, tutte le risorse indipendenti dalla lingua vengono collocate nell'assembly principale. Questo passaggio del processo di compilazione comporta tale classificazione.

Le azioni di compilazione di ApplicationDefinition, Page e Resource nel file di progetto possono essere ampliate con i metadati Localizable, i cui valori accettabili sono true e false, che indicano se il file è specifico della lingua o indipendente dalla lingua.

Compilazione principale

Il passaggio principale della compilazione implica la compilazione dei file di codice. Tale operazione viene gestita dalla logica nei file delle destinazioni specifiche del linguaggio Microsoft.CSharp.targets e Microsoft.VisualBasic.targets. Se in base all'euristica è stato stabilito che sia sufficiente un unico passaggio del compilatore di markup, allora viene generato l'assembly principale. Tuttavia, se uno o più file XAML nel progetto possiedono riferimenti a tipi definiti localmente, viene generato un file DLL temporaneo e gli assembly finali dell'applicazione potranno essere creati una volta completato il secondo passaggio della compilazione del markup.

Generazione di manifesti

Al termine del processo di compilazione, una volta creati tutti gli assembly e i file di dati dell'applicazione, vengono generati i manifesti ClickOnce per l'applicazione.

Il file del manifesto di distribuzione descrive il modello di distribuzione, ovvero la versione corrente, il comportamento di aggiornamento e l'identità dell'editore insieme alla firma digitale. Questo manifesto deve essere creato dagli amministratori che gestiscono la distribuzione. L'estensione di file è xbap per le XAML browser applications (XBAPs) e application per le applicazioni installate. La prima viene stabilita dalla proprietà del progetto HostInBrowser e, di conseguenza, il manifesto identifica l'applicazione come ospitata da browser.

Il manifesto dell'applicazione, un file con estensione exe.manifest, descrive gli assembly e le librerie dipendenti dell'applicazione ed elenca le autorizzazioni richieste dalla stessa. Questo file deve essere creato dallo sviluppatore di applicazioni. Per avviare un'applicazione ClickOnce, occorre aprire il file manifesto di distribuzione dell'applicazione.

Questi file manifesto vengono sempre creati per le applicazioni XBAPs. Non vengono invece creati per le applicazioni installate, a meno che la proprietà GenerateManifests non sia specificata nel file di progetto con il valore true.

Le applicazioni XBAPs ottengono due autorizzazioni aggiuntive oltre a quelle assegnate alle applicazioni dell'area Internet tipiche: WebBrowserPermission e MediaPermission. Il sistema di compilazione WPF dichiara le suddette autorizzazioni nel manifesto dell'applicazione.

Supporto per compilazioni incrementali

Il sistema di compilazione WPF fornisce un supporto per le compilazioni incrementali. Tale supporto consente di rilevare le modifiche apportate al markup o al codice e compilare soltanto gli elementi interessati dalle modifiche. Il meccanismo di compilazione incrementale utilizza i seguenti file:

  • Un file $(NomeAssembly)_MarkupCompiler.Cache per gestire lo stato del compilatore corrente.

  • Un file $(NomeAssembly)_MarkupCompiler.lref per memorizzare nella cache i file XAML con riferimenti a tipi definiti localmente.

Di seguito viene riportato un insieme di regole relative alla compilazione incrementale:

  • Il file è l'unità più piccola in cui il sistema di compilazione rileva le modifiche. Nel caso di un file di codice, pertanto, tale sistema non è in grado di rilevare la modifica di un tipo né l'aggiunta di codice. Lo stesso vale per i file di progetto.

  • Il meccanismo di compilazione incrementale deve tenere conto del fatto che una pagina XAML definisce una classe o utilizza altre classi.

  • Se le voci Reference vengono modificate, ricompilare tutte le pagine.

  • Se un file di codice viene modificato, ricompilare tutte le pagine con riferimenti a tipi definiti localmente.

  • Se un file XAML viene modificato:

    • Se il codice XAML è dichiarato come Page nel progetto: se il codice XAML non possiede riferimenti a tipi definiti localmente, ricompilare il codice XAML e tutte le pagine XAML con riferimenti locali; se il codice XAML possiede riferimenti locali, ricompilare tutte le pagine XAML con riferimenti locali.

    • Se il codice XAML è dichiarato come ApplicationDefinition nel progetto: ricompilare tutte le pagine XAML, poiché ogni codice XAML possiede un riferimento a un tipo Application che può essere stato modificato.

  • Se il file di progetto dichiara un file di codice come definizione di applicazione anziché un file XAML:

    • Controllare se il valore di ApplicationClassName nel file di progetto è stato modificato, ovvero se è presente un nuovo tipo di applicazione. In caso affermativo, ricompilare l'intera applicazione.

    • In caso contrario, ricompilare tutte le pagine XAML con riferimenti locali.

  • Se un file di progetto viene modificato: applicare tutte le regole elencate in precedenza e stabilire gli elementi da ricompilare. Le modifiche alle seguenti proprietà comportano una ricompilazione totale: AssemblyName, IntermediateOutputPath, RootNamespace e HostInBrowser.

Di seguito vengono riportati i possibili scenari di ricompilazione:

  • Viene ricompilata l'intera applicazione.

  • Vengono ricompilati soltanto i file XAML con riferimenti a tipi definiti localmente.

  • Non avviene alcuna ricompilazione, in quanto il progetto non ha subito modifiche.

Vedere anche

Concetti

Distribuzione di un'applicazione WPF (WPF)

URI di tipo pack in WPF

File di dati e di risorse dell'applicazione WPF.

Altre risorse

Informazioni di riferimento su MSBuild WPF

Cronologia delle modifiche

Data

Cronologia

Motivo

Novembre 2010

Aggiunta di un esempio mancante di Visual Basic.

Correzione di bug nel contenuto.