Dela via


Kompilera ett WPF-program

Windows Presentation Foundation-program (WPF) kan skapas som körbara .NET Framework-filer (.exe), bibliotek (.dll) eller en kombination av båda typerna av sammansättningar. Det här avsnittet beskriver hur du skapar WPF-program och beskriver de viktigaste stegen i byggprocessen.

Skapa ett WPF-program

Ett WPF-program kan kompileras på följande sätt:

WPF-byggpipeline

När ett WPF-projekt skapas anropas kombinationen av språkspecifika och WPF-specifika mål. Processen att genomföra dessa mål kallas för bygg-pipeline, och de viktigaste stegen illustreras i följande bild.

WPF-byggprocess

Förbyggda initialiseringar

Innan du skapar bestämmer MSBuild platsen för viktiga verktyg och bibliotek, inklusive följande:

  • The .NET Framework.

  • Windows SDK-katalogerna.

  • Platsen för WPF-referenssammansättningar.

  • Egenskapen för sökvägar för assembly.

Den första platsen där MSBuild söker efter sammansättningar är referenssammansättningens katalog (%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\). Under det här steget initierar byggprocessen även de olika egenskaperna och objektgrupperna och utför alla nödvändiga rensningar.

Åtgärda referenser

Byggprocessen letar upp och binder de sammansättningar som krävs för att skapa programprojektet. Den här logiken finns i ResolveAssemblyReference uppgift. Alla sammansättningar som deklareras som Reference i projektfilen tillhandahålls till uppgiften tillsammans med information om sökvägar och metadata för sammansättningar som redan är installerade i systemet. Uppgiften söker efter sammansättningar och använder den installerade sammansättningens metadata för att filtrera bort de WPF-kärnsammansättningar som inte behöver visas i utdatamanifesten. Detta görs för att undvika redundant information i ClickOnce-manifesten. Eftersom PresentationFramework.dll till exempel kan betraktas som representativa för ett program som bygger på och för WPF, och eftersom alla WPF-sammansättningar finns på samma plats på varje dator som har .NET Framework installerat, behöver du inte inkludera all information om alla .NET Framework-referenssammansättningar i manifesten.

Markeringskompilering – Pass 1

I det här steget parsas och kompileras XAML-filer så att körningen inte ägnar tid åt att parsa XML och verifiera egenskapsvärden. Den kompilerade XAML-filen är förtokeniserad så att det vid körningen bör gå mycket snabbare att läsa in den än att läsa in en XAML-fil.

Under det här steget utförs följande aktiviteter för varje XAML-fil som är ett Page byggobjekt:

  1. XAML-filen parsas av markeringskompilatorn.

  2. En kompilerad representation skapas för XAML och kopieras till mappen obj\Release.

  3. En CodeDOM-representation av en ny partiell klass skapas och kopieras till mappen obj\Release.

Dessutom genereras en språkspecifik kodfil för varje XAML-fil. För en Page1.xaml-sida i ett Visual Basic-projekt genereras till exempel en Page1.g.vb. för en Sida1.xaml-sida i ett C#-projekt genereras en Page1.g.cs. ".g" i filnamnet anger att filen genereras kod som har en partiell klassdeklaration för elementet på den översta nivån i markeringsfilen (till exempel Page eller Window). Klassen deklareras med partial-modifieraren i C# (Extends i Visual Basic) för att indikera att det finns en annan deklaration för klassen någon annanstans, vanligtvis i filen bakom koden Page1.xaml.cs.

Den partiella klassen sträcker sig från lämplig basklass (till exempel Page för en sida) och implementerar System.Windows.Markup.IComponentConnector-gränssnittet. Det IComponentConnector gränssnittet har metoder för att initiera en komponent och ansluta namn och händelser på element i dess innehåll. Därför har den genererade kodfilen en metodimplementering som följande:

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

Som standard körs markeringskompilering i samma AppDomain som MSBuild-motorn. Detta ger betydande prestandavinster. Det här beteendet kan växlas med egenskapen AlwaysCompileMarkupFilesInSeparateDomain. Detta har fördelen att ta bort alla referenssammansättningar genom att ta bort den separata AppDomain.

Markeringskompilering – pass 2

Alla XAML-sidor kompileras inte vid markeringskompileringens pass 1. XAML-filer som har lokalt definierade typreferenser (referenser till typer som definierats i kod någon annanstans i samma projekt) är undantagna från kompilering just nu. Det beror på att dessa lokalt definierade typer bara finns i källan och ännu inte har kompilerats. För att fastställa detta använder parsern heuristik som omfattar att söka efter objekt som x:Name i markeringsfilen. När en sådan instans hittas skjuts markeringsfilens kompilering upp tills kodfilerna har kompilerats, varefter det andra kompileringspasset för markering bearbetar dessa filer.

Filklassificering

Byggprocessen placerar utdatafiler i olika resursgrupper baserat på vilken programsammansättning de ska placeras i. I ett typiskt icke-lokaliserat program placeras alla datafiler som markerats som Resource i huvudsammansättningen (körbara eller bibliotek). När UICulture anges i projektet placeras alla kompilerade XAML-filer och de resurser som är specifikt markerade som språkspecifika i satellitresurssammansättningen. Dessutom placeras alla språkneutrala resurser i huvudsammansättningen. I det här steget i byggprocessen görs den bestämningen.

De ApplicationDefinition, Pageoch Resource byggåtgärderna i projektfilen kan utökas med Localizable metadata (acceptabla värden är true och false), som avgör om filen är språkspecifik eller språkneutral.

Core-kompilering

Det grundläggande kompileringssteget omfattar kompilering av kodfiler. Detta samordnas av logik i de språkspecifika målfilerna Microsoft.CSharp.targets och Microsoft.VisualBasic.targets. Om heuristiken har fastställt att en enda passering av markeringskompilatorn är tillräcklig genereras huvudsammansättningen. Men om en eller flera XAML-filer i projektet har referenser till lokalt definierade typer genereras en tillfällig .dll fil så att de slutliga programsammansättningarna kan skapas när den andra markeringskompileringen har slutförts.

Manifestgenerering

När alla programsammansättningar och innehållsfiler är klara i slutet av byggprocessen genereras ClickOnce-manifesten för programmet.

Distributionsmanifestfilen beskriver distributionsmodellen: den aktuella versionen, uppdateringsbeteendet och utgivarens identitet tillsammans med digital signatur. Det här manifestet är avsett att skapas av administratörer som hanterar distributionen. Filtillägget är .xbap (för XAML-webbläsarprogram (XBAPs)) och .application för installerade program. Det förra styrs av HostInBrowser projektegenskap och därför identifierar manifestet programmet som webbläsarhanterat.

Programmanifestet (en .exe.manifestfil) beskriver programsammansättningar och beroende bibliotek och listar behörigheter som krävs av programmet. Den här filen är avsedd att skapas av programutvecklaren. För att starta ett ClickOnce-program öppnar en användare programmets distributionsmanifestfil.

Dessa manifestfiler skapas alltid för XBAP:er. För installerade program skapas de inte om inte egenskapen GenerateManifests anges i projektfilen med värdet true.

XBAP:er får ytterligare två behörigheter utöver de behörigheter som tilldelats till vanliga Internetzonprogram: WebBrowserPermission och MediaPermission. WPF-byggsystemet deklarerar dessa behörigheter i programmanifestet.

Inkrementellt byggstöd

WPF-byggsystemet ger stöd för inkrementella versioner. Det är ganska intelligent när det gäller att identifiera ändringar som gjorts i markering eller kod, och det kompilerar endast de artefakter som påverkas av ändringen. Den inkrementella byggmekanismen använder följande filer:

  • En $(AssemblyName)_MarkupCompiler.Cache-fil för att upprätthålla aktuellt kompilatortillstånd.

  • En $(AssemblyName-)_MarkupCompiler.lref-fil som cachelagrar XAML-filerna med referenser till lokalt definierade typer.

Följande är en uppsättning regler som styr inkrementell bygge:

  • Filen är den minsta enhet där byggsystemet identifierar ändringar. För en kodfil kan byggsystemet alltså inte avgöra om en typ har ändrats eller om koden har lagts till. Samma gäller för projektfiler.

  • Den inkrementella byggmekanismen måste vara medveten om att en XAML-sida antingen definierar en klass eller använder andra klasser.

  • Om Reference-poster ändras, kompilera då om alla sidor.

  • Om en kodfil ändras, kompilera om alla sidor med lokalt definierade typreferenser.

  • Om en XAML-fil ändras:

    • Om XAML deklareras som Page i projektet: om XAML inte har lokalt definierade typreferenser, kompilera om XAML plus alla XAML-sidor med lokala referenser. Om XAML har lokala referenser kan du kompilera om alla XAML-sidor med lokala referenser.

    • Om XAML deklareras som ApplicationDefinition i projektet: kompilera om alla XAML-sidor (orsak: varje XAML har en referens till en Application typ som kan ha ändrats).

  • Om projektfilen deklarerar en kodfil som programdefinition i stället för en XAML-fil:

    • Kontrollera om ApplicationClassName värdet i projektfilen har ändrats (finns det en ny programtyp?). I så fall kan du kompilera om hela programmet.

    • Annars kan du kompilera om alla XAML-sidor med lokala referenser.

  • Om en projektfil ändras: tillämpa alla föregående regler och se vad som behöver kompileras om. Ändringar i följande egenskaper utlöser en fullständig omkompilering: AssemblyName, IntermediateOutputPath, RootNamespaceoch HostInBrowser.

Följande omkompileringsscenarier är möjliga:

  • Hela programmet kompileras om.

  • Endast de XAML-filer som har lokalt definierade typreferenser kompileras om.

  • Ingenting är omkompilerat (om inget i projektet har ändrats).

Se även