Kompilowanie aplikacji WPF

Aplikacje programu Windows Presentation Foundation (WPF) można tworzyć jako pliki wykonywalne programu .NET Framework (.exe), biblioteki (.dll) lub kombinację obu typów zestawów. W tym temacie przedstawiono sposób kompilowania aplikacji WPF i opisano kluczowe kroki procesu kompilacji.

Kompilowanie aplikacji WPF

Aplikację WPF można skompilować w następujący sposób:

Potok kompilacji WPF

Podczas kompilowania projektu WPF wywoływana jest kombinacja elementów docelowych specyficznych dla języka i WPF. Proces wykonywania tych obiektów docelowych jest nazywany potokiem kompilacji, a kluczowe kroki przedstawiono na poniższej ilustracji.

WPF build process

Inicjowanie przed kompilacją

Przed utworzeniem program MSBuild określa lokalizację ważnych narzędzi i bibliotek, w tym następujące:

  • The .NET Framework.

  • Katalogi zestawu Windows SDK.

  • Lokalizacja zestawów odwołań WPF.

  • Właściwość ścieżek wyszukiwania zestawów.

Pierwszą lokalizacją, w której program MSBuild wyszukuje zestawy, jest katalog zestawu odwołania (%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\). W tym kroku proces kompilacji inicjuje również różne właściwości i grupy elementów i wykonuje wszelkie wymagane prace oczyszczania.

Rozpoznawanie odwołań

Proces kompilacji lokalizuje i wiąże zestawy wymagane do skompilowania projektu aplikacji. Ta logika jest zawarta ResolveAssemblyReference w zadaniu. Wszystkie zestawy zadeklarowane jako Reference w pliku projektu są dostarczane do zadania wraz z informacjami na temat ścieżek wyszukiwania i metadanych zestawów już zainstalowanych w systemie. Zadanie wyszukuje zestawy i używa metadanych zainstalowanego zestawu do filtrowania tych podstawowych zestawów WPF, które nie muszą być wyświetlane w manifestach wyjściowych. Należy to zrobić, aby uniknąć nadmiarowych informacji w manifestach Technologii ClickOnce. Ponieważ na przykład plik PresentationFramework.dll może być uważany za reprezentatywny dla aplikacji utworzonej i dla platformy WPF, a ponieważ wszystkie zestawy WPF istnieją w tej samej lokalizacji na każdym komputerze, na którym jest zainstalowany program .NET Framework, nie ma potrzeby dołączania wszystkich informacji do wszystkich zestawów odwołań programu .NET Framework w manifestach.

Kompilacja znaczników — przekazywanie 1

W tym kroku pliki XAML są analizowane i kompilowane, dzięki czemu środowisko uruchomieniowe nie poświęca czasu na analizowanie kodu XML i weryfikowanie wartości właściwości. Skompilowany plik XAML jest wstępnie tokenizowany, dzięki czemu ładowanie pliku XAML w czasie wykonywania powinno być znacznie szybsze niż ładowanie pliku XAML.

W tym kroku są wykonywane następujące działania dla każdego pliku XAML, który jest elementem Page kompilacji:

  1. Plik XAML jest analizowany przez kompilator znaczników.

  2. Skompilowana reprezentacja jest tworzona dla tego kodu XAML i kopiowana do folderu obj\Release.

  3. Zostanie utworzona reprezentacja CodeDOM nowej klasy częściowej i skopiowana do folderu obj\Release.

Ponadto plik kodu specyficzny dla języka jest generowany dla każdego pliku XAML. Na przykład w przypadku strony Page1.xaml w projekcie Visual Basic jest generowana strona Page1.g.vb; dla strony Page1.xaml w projekcie języka C# generowany jest plik Page1.g.cs. Znak ".g" w nazwie pliku wskazuje, że plik jest generowany kod z częściową deklaracją klasy dla elementu najwyższego poziomu pliku znaczników (na przykład Page lub Window). Klasa jest zadeklarowana za pomocą partial modyfikatora w języku C# (Extends w Visual Basic), aby wskazać, że istnieje inna deklaracja dla klasy w innym miejscu, zwykle w pliku za kodem Page1.xaml.cs.

Klasa częściowa rozciąga się od odpowiedniej klasy bazowej (takiej jak Page dla strony) i implementuje System.Windows.Markup.IComponentConnector interfejs. Interfejs IComponentConnector zawiera metody inicjowania składnika i łączenia nazw i zdarzeń na elementach w jego zawartości. W związku z tym wygenerowany plik kodu ma implementację metody podobną do następującej:

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

Domyślnie kompilacja znaczników jest uruchamiana w taki sam sposób AppDomain jak aparat MSBuild. Zapewnia to znaczne wzrosty wydajności. To zachowanie może być przełączane za AlwaysCompileMarkupFilesInSeparateDomain pomocą właściwości . Ma to zaletę zwalniania wszystkich zestawów odwołań przez zwolnienie oddzielnego AppDomainobiektu .

Kompilacja znaczników — przekazywanie 2

Nie wszystkie strony XAML są kompilowane podczas kompilacji znaczników z przekazywaniem 1. Pliki XAML, które mają lokalnie zdefiniowane odwołania do typów (odwołania do typów zdefiniowanych w kodzie w innym miejscu tego samego projektu) są obecnie wykluczone z kompilacji. Dzieje się tak, ponieważ te lokalnie zdefiniowane typy istnieją tylko w źródle i nie zostały jeszcze skompilowane. Aby to określić, analizator używa heurystyki, które obejmują wyszukiwanie elementów, takich jak x:Name w pliku znaczników. Po znalezieniu takiego wystąpienia kompilacja pliku znaczników jest odroczona do momentu skompilowania plików kodu, po którym druga kompilacja znaczników przekazuje te pliki.

Klasyfikacja plików

Proces kompilacji umieszcza pliki wyjściowe w różnych grupach zasobów na podstawie zestawu aplikacji, w którym zostaną umieszczone. W typowej aplikacji nielokalizowanej wszystkie pliki danych oznaczone jako Resource są umieszczane w głównym zestawie (wykonywalnym lub bibliotece). Po UICulture ustawieniu w projekcie wszystkie skompilowane pliki XAML i te zasoby oznaczone specjalnie jako specyficzne dla języka są umieszczane w zestawie zasobów satelickich. Ponadto wszystkie zasoby neutralne dla języka są umieszczane w głównym zestawie. W tym kroku procesu kompilacji jest to określone.

ApplicationDefinitionAkcje kompilacji , Pagei Resource w pliku projektu można rozszerzyć o Localizable metadane (dopuszczalne wartości to true i false), które określają, czy plik jest specyficzny dla języka, czy neutralny dla języka.

Kompilacja podstawowa

Podstawowy krok kompilacji obejmuje kompilację plików kodu. Jest to orkiestrowane przez logikę w plikach docelowych specyficznych dla języka Microsoft.CSharp.targets i Microsoft.VisualBasic.targets. Jeśli heurystyka ustaliła, że wystarczy pojedyncze przekazanie kompilatora znaczników, zostanie wygenerowany główny zestaw. Jeśli jednak co najmniej jeden plik XAML w projekcie zawiera odwołania do lokalnie zdefiniowanych typów, zostanie wygenerowany tymczasowy plik dll, aby końcowe zestawy aplikacji mogły zostać utworzone po zakończeniu drugiego przekazywania kompilacji znaczników.

Generowanie manifestu

Po zakończeniu procesu kompilacji wszystkie zestawy aplikacji i pliki zawartości są gotowe, manifesty Technologii ClickOnce dla aplikacji są generowane.

Plik manifestu wdrożenia opisuje model wdrażania: bieżącą wersję, zachowanie aktualizacji i tożsamość wydawcy wraz z podpisem cyfrowym. Ten manifest ma być utworzony przez administratorów, którzy obsługują wdrażanie. Rozszerzenie pliku to .xbap (dla aplikacji przeglądarki XAML (XBAPs)) i .application dla zainstalowanych aplikacji. Pierwszy element jest dyktowany przez HostInBrowser właściwość projektu, a w rezultacie manifest identyfikuje aplikację jako hostowaną w przeglądarce.

Manifest aplikacji (plik .exe.manifest) opisuje zestawy aplikacji i biblioteki zależne oraz wyświetla listę uprawnień wymaganych przez aplikację. Ten plik ma zostać utworzony przez dewelopera aplikacji. Aby uruchomić aplikację ClickOnce, użytkownik otwiera plik manifestu wdrożenia aplikacji.

Te pliki manifestu są zawsze tworzone dla XBAPs. W przypadku zainstalowanych aplikacji nie są tworzone, chyba że GenerateManifests właściwość jest określona w pliku projektu o wartości true.

XBAPs uzyskać dwa dodatkowe uprawnienia do tych uprawnień przypisanych do typowych aplikacji strefy internetowej: WebBrowserPermission i MediaPermission. System kompilacji WPF deklaruje te uprawnienia w manifeście aplikacji.

Obsługa kompilacji przyrostowej

System kompilacji WPF zapewnia obsługę kompilacji przyrostowych. Jest dość inteligentny w zakresie wykrywania zmian wprowadzonych w adiustacji lub kodzie i kompiluje tylko te artefakty, których dotyczy zmiana. Mechanizm kompilacji przyrostowej używa następujących plików:

  • Plik $(AssemblyName)_MarkupCompiler.Cache w celu zachowania bieżącego stanu kompilatora.

  • Plik $(AssemblyName)_MarkupCompiler.lref do buforowania plików XAML z odwołaniami do lokalnie zdefiniowanych typów.

Poniżej przedstawiono zestaw reguł dotyczących kompilacji przyrostowej:

  • Plik jest najmniejszą jednostką, w której system kompilacji wykrywa zmianę. W przypadku pliku kodu system kompilacji nie może określić, czy typ został zmieniony lub czy został dodany kod. Te same blokady są przechowywane dla plików projektu.

  • Mechanizm kompilacji przyrostowej musi być świadomy, że strona XAML definiuje klasę lub używa innych klas.

  • Jeśli Reference wpisy zostaną zmienione, ponownie skompiluj wszystkie strony.

  • Jeśli plik kodu ulegnie zmianie, ponownie skompiluj wszystkie strony przy użyciu odwołań do typu zdefiniowanego lokalnie.

  • Jeśli plik XAML ulegnie zmianie:

    • Jeśli kod XAML jest zadeklarowany jako Page w projekcie: jeśli kod XAML nie ma lokalnie zdefiniowanych odwołań do typu, ponownie skompiluj kod XAML i wszystkie strony XAML z lokalnymi odwołaniami; jeśli kod XAML zawiera odwołania lokalne, ponownie skompiluj wszystkie strony XAML z lokalnymi odwołaniami.

    • Jeśli kod XAML jest zadeklarowany jako ApplicationDefinition w projekcie: przekompiluj wszystkie strony XAML (przyczyna: każdy kod XAML ma odwołanie do Application typu, który mógł ulec zmianie).

  • Jeśli plik projektu deklaruje plik kodu jako definicję aplikacji zamiast pliku XAML:

    • Sprawdź, czy ApplicationClassName wartość w pliku projektu została zmieniona (czy istnieje nowy typ aplikacji?). Jeśli tak, ponownie skompiluj całą aplikację.

    • W przeciwnym razie ponownie skompiluj wszystkie strony XAML przy użyciu lokalnych odwołań.

  • Jeśli plik projektu ulegnie zmianie: zastosuj wszystkie powyższe reguły i sprawdź, co należy ponownie skompilować. Zmiany w następujących właściwościach wyzwalają kompletną ponowną kompilację: AssemblyName, , IntermediateOutputPathRootNamespacei HostInBrowser.

Możliwe są następujące scenariusze ponownego kompilu:

  • Cała aplikacja zostanie ponownie skompilowana.

  • Tylko te pliki XAML, które mają lokalnie zdefiniowane odwołania do typów, są ponownie komilowane.

  • Nic nie zostanie ponownie skompilowane (jeśli nic w projekcie nie uległo zmianie).

Zobacz też