Delen via


Een WPF-toepassing compileren

WpF-toepassingen (Windows Presentation Foundation) kunnen worden gebouwd als uitvoerbare .NET Framework-bestanden (.exe), bibliotheken (.dll) of een combinatie van beide typen assembly's. In dit onderwerp wordt uitgelegd hoe u WPF-toepassingen bouwt en de belangrijkste stappen in het buildproces beschrijft.

Een WPF-toepassing bouwen

Een WPF-toepassing kan op de volgende manieren worden gecompileerd:

WPF Bouwpijplijn

Wanneer een WPF-project wordt gebouwd, wordt de combinatie van taalspecifieke en WPF-specifieke doelen aangeroepen. Het proces voor het uitvoeren van deze doelen wordt de build-pijplijn genoemd en de belangrijkste stappen worden geïllustreerd in de volgende afbeelding.

WPF-buildproces

Initialisaties voorafgaand aan de bouw

Voordat u gaat bouwen, bepaalt MSBuild de locatie van belangrijke hulpprogramma's en bibliotheken, waaronder de volgende:

  • Het .NET Framework.

  • De Windows SDK-mappen.

  • De locatie van WPF-referentieassembly's.

  • De eigenschap voor de assembly-zoekpaden.

De eerste locatie waar MSBuild zoekt naar assemblies is de map van referentieassembly's (%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\). Tijdens deze stap initialiseert het buildproces ook de verschillende eigenschappen en itemgroepen en voert het vereiste opschoningswerk uit.

Verwijzingen oplossen

Het buildproces zoekt en bindt de assembly's die nodig zijn om het toepassingsproject te bouwen. Deze logica is opgenomen in de ResolveAssemblyReference taak. Alle assembly's die zijn gedeclareerd als Reference in het projectbestand, worden aan de taak verstrekt, samen met informatie over de zoekpaden en metagegevens voor assembly's die al op het systeem zijn geïnstalleerd. De taak zoekt assembly's op en gebruikt de metagegevens van de geïnstalleerde assembly om die kern-WPF-assembly's te filteren die niet in de uitvoermanifesten moeten worden weergegeven. Dit wordt gedaan om redundante informatie in de ClickOnce-manifesten te voorkomen. Omdat PresentationFramework.dll bijvoorbeeld als representatief kunnen worden beschouwd voor een toepassing die is gebouwd op en voor WPF, en omdat alle WPF-assembly's op dezelfde locatie aanwezig zijn op elke computer waarop .NET Framework is geïnstalleerd, hoeft u niet alle informatie op te nemen over alle .NET Framework-referentieassembly's in de manifesten.

Compilatie van markeringen- Pass 1

In deze stap worden XAML-bestanden geparseerd en gecompileerd, zodat de runtime geen tijd besteedt aan het parseren van XML en het valideren van eigenschapswaarden. Het gecompileerde XAML-bestand is vooraf tokenized, zodat het laden tijdens runtime veel sneller moet zijn dan het laden van een XAML-bestand.

Tijdens deze stap vinden de volgende activiteiten plaats voor elk XAML-bestand dat een Page build-item is:

  1. Het XAML-bestand wordt geparseerd door de opmaakcompilator.

  2. Er wordt een gecompileerde weergave gemaakt voor die XAML en gekopieerd naar de map obj\Release.

  3. Er wordt een CodeDOM-weergave van een nieuwe gedeeltelijke klasse gemaakt en gekopieerd naar de map obj\Release.

Daarnaast wordt er een taalspecifiek codebestand gegenereerd voor elk XAML-bestand. Voor een Pagina1.xaml-pagina in een Visual Basic-project wordt bijvoorbeeld een Page1.g.vb gegenereerd; voor een Page1.xaml-pagina in een C#-project wordt een Page1.g.cs gegenereerd. De '.g' in de bestandsnaam geeft aan dat het bestand is gegenereerd met een gedeeltelijke klassedeclaratie voor het element op het hoogste niveau van het opmaakbestand (zoals Page of Window). De klasse wordt gedeclareerd met de partial modifier in C# (Extends in Visual Basic) om aan te geven dat er elders een andere declaratie is voor de klasse, meestal in het bestand achter de code Page1.xaml.cs.

De gedeeltelijke klasse is een uitbreiding van de juiste basisklasse (zoals Page voor een pagina) en implementeert de System.Windows.Markup.IComponentConnector interface. De IComponentConnector-interface bevat methoden om een onderdeel te initialiseren en namen en gebeurtenissen te verbinden op elementen in de inhoud. Daarom heeft het gegenereerde codebestand een methode-implementatie zoals de volgende:

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

Standaard wordt de compilatie van markeringen uitgevoerd in dezelfde AppDomain als de MSBuild-engine. Dit biedt aanzienlijke prestatieverbeteringen. Dit gedrag kan worden ingeschakeld met de eigenschap AlwaysCompileMarkupFilesInSeparateDomain. Dit heeft als voordeel dat alle referentie-assembly's worden ontladen door de afzonderlijke AppDomainte ontladen.

Compilatie van markeringen- Pass 2

Niet alle XAML-pagina's worden gecompileerd tijdens fase 1 van de mark-up compilatie. XAML-bestanden met lokaal gedefinieerde typeverwijzingen (verwijzingen naar typen die elders in hetzelfde project zijn gedefinieerd) zijn op dit moment uitgesloten van compilatie. Dit komt doordat deze lokaal gedefinieerde typen alleen bestaan in de bron en nog niet zijn gecompileerd. Om dit te bepalen, gebruikt de parser heuristieken die betrekking hebben op het zoeken naar items zoals x:Name in het opmaakbestand. Wanneer een dergelijk geval wordt gevonden, wordt de compilatie van het mark-up bestand uitgesteld totdat de codebestanden zijn gecompileerd, waarna de tweede mark-up compilatie deze bestanden verwerkt.

Bestandsclassificatie

Het buildproces plaatst uitvoerbestanden in verschillende resourcegroepen op basis van de toepassingsassembly waarin ze worden geplaatst. In een typische niet-gelokaliseerde toepassing worden alle gegevensbestanden die zijn gemarkeerd als Resource in de hoofdassembly geplaatst (uitvoerbaar bestand of bibliotheek). Wanneer UICulture is ingesteld in het project, worden alle gecompileerde XAML-bestanden en die resources die specifiek zijn gemarkeerd als taalspecifieke, in de satellietresourceassembly geplaatst. Bovendien worden alle taalneutrale resources in de hoofdassemblage geplaatst. In deze stap van het buildproces wordt die beslissing genomen.

De ApplicationDefinition, Pageen Resource bouwacties in het projectbestand kunnen worden uitgebreid met de Localizable metagegevens (acceptabele waarden zijn true en false), die bepaalt of het bestand taalspecifiek of taalneutraal is.

Kerncompilatie

De kerncompilatiestap omvat het compileren van codebestanden. Dit wordt ingedeeld op basis van logica in de taalspecifieke doelenbestanden Microsoft.CSharp.targets en Microsoft.VisualBasic.targets. Als de heuristiek heeft vastgesteld dat één pass van de markeringscompilator voldoende is, wordt de hoofdassembly gegenereerd. Als een of meer XAML-bestanden in het project echter verwijzingen hebben naar lokaal gedefinieerde typen, wordt er een tijdelijk .dll bestand gegenereerd, zodat de uiteindelijke toepassingsassembly's kunnen worden gemaakt nadat de tweede doorgang van de compilatie van markeringen is voltooid.

Manifestgeneratie

Aan het einde van het buildproces worden, nadat alle assembly's en inhoudsbestanden van de toepassing gereed zijn, de ClickOnce-manifesten voor de toepassing gegenereerd.

In het distributiemanifestbestand wordt het implementatiemodel beschreven: de huidige versie, het updategedrag en de uitgeversidentiteit, samen met digitale handtekening. Dit manifest is bedoeld om te worden geschreven door beheerders die de implementatie verwerken. De bestandsextensie is .xbap (voor XAML-browsertoepassingen (XBAPs)) en .application voor geïnstalleerde toepassingen. De eerste wordt bepaald door de HostInBrowser-projecteigenschap en daardoor identificeert het manifest de toepassing als in de browser gehost.

In het toepassingsmanifest (een .exe.manifestbestand) worden de assembly's en afhankelijke bibliotheken van de toepassing beschreven en worden machtigingen vermeld die vereist zijn voor de toepassing. Dit bestand is bedoeld om te worden geschreven door de toepassingsontwikkelaar. Als u een ClickOnce-toepassing wilt starten, opent een gebruiker het manifestbestand voor de implementatie van de toepassing.

Deze manifestbestanden worden altijd gemaakt voor XBAPs. Voor geïnstalleerde toepassingen worden ze niet gemaakt, tenzij de eigenschap GenerateManifests is opgegeven in het projectbestand met waarde true.

XBAPs krijgen twee extra machtigingen boven en boven die machtigingen die zijn toegewezen aan typische internetzonetoepassingen: WebBrowserPermission en MediaPermission. Het WPF-buildsysteem declareert deze machtigingen in het toepassingsmanifest.

Ondersteuning voor incrementele build

Het WPF-buildsysteem biedt ondersteuning voor incrementele builds. Het is redelijk intelligent om wijzigingen te detecteren die zijn aangebracht in markeringen of code en compileert alleen die artefacten die worden beïnvloed door de wijziging. Het incrementele buildmechanisme maakt gebruik van de volgende bestanden:

  • Een $(AssemblyName)_MarkupCompiler.Cache-bestand om de huidige compilerstatus te behouden.

  • Een $(AssemblyName)_MarkupCompiler.lref-bestand om de XAML-bestanden in de cache op te slaan met verwijzingen naar lokaal gedefinieerde typen.

Hier volgt een set regels voor incrementele build:

  • Het bestand is de kleinste eenheid waarmee het buildsysteem wijzigingen detecteert. Voor een codebestand kan het buildsysteem dus niet zien of een type is gewijzigd of dat er code is toegevoegd. Hetzelfde geldt voor projectbestanden.

  • Het incrementele buildmechanisme moet cognizant zijn dat een XAML-pagina een klasse definieert of andere klassen gebruikt.

  • Als Reference vermeldingen worden gewijzigd, moet u alle pagina's opnieuw compileren.

  • Als een codebestand wordt gewijzigd, moet u alle pagina's opnieuw compileren met lokaal gedefinieerde typeverwijzingen.

  • Als een XAML-bestand wordt gewijzigd:

    • Als XAML als Page in het project wordt gedeclareerd: als de XAML geen lokaal gedefinieerde typeverwijzingen heeft, moet u die XAML plus alle XAML-pagina's met lokale verwijzingen opnieuw compileren; als de XAML lokale verwijzingen heeft, moet u alle XAML-pagina's opnieuw compileren met lokale verwijzingen.

    • Als XAML wordt gedeclareerd als ApplicationDefinition in het project: hercompileren van alle XAML-pagina's (reden: elke XAML verwijst naar een Application type dat mogelijk is gewijzigd).

  • Als het projectbestand een codebestand als toepassingsdefinitie declareert in plaats van een XAML-bestand:

    • Controleer of de ApplicationClassName waarde in het projectbestand is gewijzigd (is er een nieuw toepassingstype?). Als dat het zo is, moet u de hele toepassing opnieuw compileren.

    • Anders moet u alle XAML-pagina's opnieuw compileren met lokale verwijzingen.

  • Als een projectbestand wordt gewijzigd: pas alle voorgaande regels toe en kijk wat er opnieuw moet worden gecompileerd. Wijzigingen in de volgende eigenschappen activeren een volledige hercompilatie: AssemblyName, IntermediateOutputPath, RootNamespaceen HostInBrowser.

De volgende scenario's voor opnieuw compileren zijn mogelijk:

  • De hele toepassing wordt opnieuw gecompileerd.

  • Alleen XAML-bestanden met lokaal gedefinieerde typeverwijzingen worden opnieuw gecompileerd.

  • Er wordt niets opnieuw gecompileerd (als er niets in het project is gewijzigd).

Zie ook