Migrace aplikací WPF na .NET Core

Tento článek popisuje kroky potřebné k migraci Windows Presentation Foundation (WPF) z .NET Framework na .NET Core 3.0. Pokud nemáte aplikaci WPF po ruce pro port, ale chcete si tento proces vyzkoušet, můžete použít ukázkovou aplikaci Bean Trader dostupnou na GitHub. Původní aplikace (cílená na .NET Framework 4.7.2) je k dispozici ve složce NetFx\BeanClient. Nejprve si vysvětlíme kroky potřebné pro obecné portování aplikací a pak si projdeme konkrétní změny, které platí pro ukázku Bean Trader.

Důležité

Dokumentace k desktopové příručce pro .NET 5 (a .NET Core) je ve stávajícím prostředí.

Vyzkoušejte pomocníka s upgradem.

Pomocník s upgradem .NET je nástroj příkazového řádku, který lze spustit na různých typech .NET Framework aplikací. Je navržený tak, aby pomáhal s upgradem .NET Framework aplikací na .NET 5. Po spuštění nástroje bude ve většině případů aplikace vyžadovat další úsilí k dokončení migrace. Součástí tohoto nástroje je instalace analyzátorů, které mohou s dokončením migrace pomoct.

Další informace najdete v tématu Upgrade Windows Forms app na .NET 5 pomocí nástroje .NET Upgrade Assistant.

Požadavky

Pokud chcete migrovat na .NET Core, musíte nejprve:

  1. Principy a aktualizace NuGet závislostí:

    1. Upgradujte NuGet závislosti a použijte <PackageReference> formát .
    2. Zkontrolujte závislosti zabezpečení nejvyšší NuGet pro .NET Core nebo .NET Standard kompatibilitu.
    3. Upgradujte NuGet balíčky na novější verze.
    4. K pochopení závislostí rozhraní .NET použijte .NET Portability Analyzer.
  2. Migrace souboru projektu do nového formátu ve stylu sady SDK:

    1. Vyberte, jestli se má cílit na .NET Core .NET Framework, nebo jenom na .NET Core.
    2. Zkopírujte do nového souboru projektu odpovídající vlastnosti a položky souboru projektu.
  3. Oprava problémů se sestavením:

    1. Přidejte odkaz na Microsoft.Windows. Balíček kompatibility.
    2. Vyhledejte a opravte rozdíly na úrovni rozhraní API.
    3. Odeberte app.config jiné části než appSettings nebo connectionStrings .
    4. V případě potřeby vygenerovaný kód vygenerujte znovu.
  4. Běhové testování:

    1. Ověřte, že portovaná aplikace funguje podle očekávání.
    2. Dejte pozor NotSupportedException na výjimky.

Informace o ukázce

Tento článek odkazuje na ukázkovou aplikaci Bean Trader, protože používá různé závislosti podobné těm, které mohou mít reálné aplikace WPF. Aplikace není velká, ale má jít o krok nahoru od Hello World z hlediska složitosti. Aplikace ukazuje některé problémy, se kterými se uživatelé mohou setkat při přenosu skutečných aplikací. Aplikace komunikuje se službou WCF, takže aby aplikace fungovala správně, musíte také spustit projekt BeanTraderServer (dostupný ve stejném úložišti GitHub) a ujistit se, že konfigurace BeanClient odkazuje na správný koncový bod. (Ve výchozím nastavení ukázka předpokládá, že server běží na stejném počítači v , což bude true, pokud http://localhost:8090 spustíte BeanTraderServer místně.)

Mějte na paměti, že tato ukázková aplikace je určena k předvedení problémů a řešení přenosů v .NET Core. Nemá předvést osvědčené postupy WPF. Ve skutečnosti záměrně zahrnuje některé antivzory, abyste se při přenosu ujistili, že při přenosu narazit alespoň na několik zajímavých výzev.

Příprava

Hlavní výzvou při migraci aplikace .NET Framework na .NET Core je to, že její závislosti mohou fungovat jinak nebo vůbec. Migrace je mnohem jednodušší, než bývala. Mnoho NuGet balíčků teď cílí na .NET Standard. Počínaje .NET Core 2.0 jsou .NET Framework a .NET Core podobné. I tak některé rozdíly (jak v podpoře z balíčků NuGet, tak i v dostupných rozhraních .NET API) zůstávají. Prvním krokem při migraci je zkontrolovat závislosti aplikace a ujistit se, že odkazy jsou ve formátu, který se snadno migruje na .NET Core.

Upgrade na <PackageReference> NuGet odkazy

Starší .NET Framework projekty obvykle vyjádí své NuGet závislosti v packages.config souboru. Nový formát souboru projektu ve stylu sady SDK odkazuje NuGet jako prvky v samotném souboru csproj, a ne v <PackageReference> samostatném konfiguračním souboru.

Při migraci mají použití odkazů <PackageReference> ve stylu dvě výhody:

  • Jedná se o styl NuGet, který je vyžadován pro nový soubor projektu .NET Core. Pokud už používáte , můžete tyto elementy souboru projektu zkopírovat a vkopírovat <PackageReference> přímo do nového projektu.
  • Na rozdíl packages.config souboru odkazují prvky pouze na závislosti nejvyšší úrovně, na které váš projekt <PackageReference> přímo závisí. Všechny ostatní tranzitivní NuGet se určí v době obnovení a zaznamenají do automaticky vygenerovaného souboru obj\project.assets.json. Díky tomu je mnohem jednodušší určit, jaké závislosti váš projekt má, což je užitečné při určování, jestli potřebné závislosti budou fungovat v .NET Core, nebo ne.

Prvním krokem při migraci aplikace .NET Framework na .NET Core je aktualizace aplikace tak, aby NuGet <PackageReference> odkazy. Visual Studio to usnadňuje. Stačí kliknout pravým tlačítkem na souborpackages.config projektu v Visual Studio souboru Průzkumník řešení a pak vybrat Migrate packages.config to PackageReference.

Upgrade na PackageReference

Zobrazí se dialogové okno s vypočtenou závislostí nejvyšší NuGet a dotazem, které další balíčky NuGet se mají povýšit na nejvyšší úroveň. Žádný z těchto dalších balíčků nemusí být pro ukázku Bean Trader nejvyšší úrovní, takže můžete zrušit zaškrtnutí všech těchto políček. Potom klikněte na OK a souborpackages.config se odebere a do souboru projektu se přidávají <PackageReference> prvky.

<PackageReference>Odkazy -style neukládá balíčky NuGet místně do složky balíčků. Místo toho se ukládají globálně jako optimalizace. Po dokončení migrace upravte soubor csproj a odeberte všechny prvky odkazující na analyzátory, které <Analyzer> dříve pocházely z .. Adresář \packages. Nedělejte si starosti. vzhledem k tomu, že NuGet balíčku, budou analyzátory zahrnuty do projektu. Stačí jenom vyčistit staré packages.config ve <Analyzer> stylu.

Kontrola NuGet balíčků

Teď, když vidíte balíčky nejvyšší NuGet, na které projekt závisí, můžete zkontrolovat, jestli jsou tyto balíčky dostupné v .NET Core. Pokud chcete zjistit, jestli balíček podporuje .NET Core, můžete se dívat na jeho závislosti na nuget.org. Komunitní web fuget.org tyto informace zřetelně zobrazuje v horní části stránky s informacemi o balíčku.

Při cílení na .NET Core 3.0 by měly fungovat všechny balíčky, které cílí na .NET Core nebo .NET Standard (protože .NET Core implementuje .NET Standard oblasti). V některých případech konkrétní verze balíčku, který se používá, nebude cílit na .NET Core ani .NET Standard, ale novější verze. V takovém případě byste měli zvážit upgrade na nejnovější verzi balíčku.

Můžete také použít balíčky .NET Framework, ale to představuje určité riziko. Rozhraní .NET Core .NET Framework povolené, protože .NET Core a .NET Framework oblasti jsou dostatečně podobné, aby tyto závislosti často fungovaly. Pokud se ale balíček pokusí použít rozhraní .NET API, které není k dispozici v .NET Core, dojde k výjimce za běhu. Proto byste měli na tyto balíčky odkazovat .NET Framework, když nejsou k dispozici žádné jiné možnosti, a pochopit, že to má zatěžující testování.

Pokud se odkazuje na balíčky, které necílují .NET Core ani .NET Standard, budete se muset zamyslet nad dalšími alternativami:

  • Existují další podobné balíčky, které je možné použít místo toho? Někdy NuGet publikuje samostatný soubor . Základní verze jejich knihoven určené speciálně pro .NET Core. Enterprise Balíčky knihoven jsou příkladem publikování v komunitě. NetCore. V jiných případech jsou pro konkrétní službu (někdy s různými názvy balíčků) k dispozici novější .NET Standard. Pokud nejsou k dispozici žádné alternativy, můžete pokračovat v používání balíčků cílených na .NET Framework s ohledem na to, že je po spuštění v .NET Core budete muset důkladně otestovat.

Ukázka Bean Trader má následující závislosti nejvyšší NuGet úrovní:

  • Pokud chcete, můžete si ho vybrat z verze 4.1.1.

    Tento balíček je .NET Standard 1.6, takže funguje na .NET Core.

  • Microsoft.CodeAnalysis.FxCopAnalyzers, verze 2.6.3
    Jedná se o meta balíček, takže není okamžitě zřejmé, které platformy podporuje, ale dokumentace uvádí, že jeho nejnovější verze (2.9.2) bude fungovat pro .NET Framework i .NET Core.

  • AsyncEx, verze 4.0.1

    Tento balíček se nezaměřuje na .NET Core, ale novější verze 5.0. To je běžné při migraci, protože NuGet balíčků .NET Standard podporu, ale starší verze projektu budou cílit jenom na .NET Framework. Pokud se rozdíl mezi verzemi liší pouze v dílčích verzích, upgrade na novější verzi je často snadný. Vzhledem k tomu, že se jedná o hlavní změnu verze, musíte být při upgradu opatrní, protože v balíčku mohou být zásadní změny. Existuje však cesta vpřed, což je dobré.

  • MahApps.Metro, verze 1.6.5

    Tento balíček se také nezaměřuje na .NET Core, ale má novější předběžnou verzi (2.0-alpha), která ano. Znovu se musíte podívat na rozbíjení změn, ale novější balíček je podporován.

Závislosti závislostí vzorku Bean Trader NuGet buď cílí na .NET Standard/.NET Core, nebo mají novější verze, takže tu pravděpodobně nebudou žádné blokující problémy.

Upgrade NuGet balíčků

Pokud je to možné, bylo by vhodné upgradovat verze všech balíčků, které cílí pouze na .NET Core nebo .NET Standard s novějšími verzemi v tomto okamžiku (s projektem stále zaměřeným na .NET Framework), aby se všechny změny způsobné rozbíjení objevily a řešit v rané fázi.

pokud byste nemuseli dělat žádné podstatné změny v existující .NET Framework verzi aplikace, může to počkat, až budete mít nový soubor projektu cílící na .net Core. upgrade NuGetch balíčků na verze, které jsou kompatibilní s .net Core, ale předem usnadňuje proces migrace, a to i po vytvoření nového souboru projektu a omezení počtu rozdílů mezi .NET Framework a verzemi .net Core aplikace.

v případě ukázky pro obchodní hospodářský program je možné snadno provést všechny nezbytné upgrady (pomocí správce balíčků NuGet Visual Studio) s jednou výjimkou: upgrade z MahApps. Metro 1.6.5 na 2,0 odhalí zásadní změny související s rozhraními api pro správu motivů a zvýraznění.

V ideálním případě by se aplikace aktualizovala tak, aby používala novější verzi balíčku (vzhledem k tomu, že je pravděpodobnější funkčnost .NET Core). V některých případech ale nemusí být proveditelné. V těchto případech NEUPGRADUJTE MahApps. metro , protože potřebné změny jsou netriviální a tento kurz se zaměřuje na migraci na .NET Core 3, ne na MahApps. Metro 2. také se jedná o ne.NET Frameworkou závislost, protože obchodník z aplikace bob uplatňuje jenom malou část MahApps. Metro. Budeme samozřejmě potřebovat testování, aby se zajistilo, že vše funguje, až se migrace dokončí. Pokud se jednalo o reálný scénář, mělo by být dobré zaslat problém pro sledování práce, která se má přesunout na MahApps. metro verze 2,0, protože migrace teď nevede k nějakému technickému dluhu.

jakmile se balíčky NuGet aktualizují na nejnovější verze, <PackageReference> skupina položek v souboru projektu ukázkového účastníka pro obchodníky by měla vypadat takto.

<ItemGroup>
  <PackageReference Include="Castle.Windsor">
    <Version>4.1.1</Version>
  </PackageReference>
  <PackageReference Include="MahApps.Metro">
    <Version>1.6.5</Version>
  </PackageReference>
  <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
    <Version>2.9.2</Version>
  </PackageReference>
  <PackageReference Include="Nito.AsyncEx">
    <Version>5.0.0</Version>
  </PackageReference>
</ItemGroup>

analýza přenositelnosti .NET Framework

jakmile pochopíte stav NuGetch závislostí projektu, další věc, kterou je potřeba zvážit, je .NET Framework závislosti rozhraní API. Nástroj analyzátor přenositelnosti .NET je užitečný pro porozumění tomu, které rozhraní API .NET vaše projekty používá, jsou k dispozici na jiných platformách .NET.

nástroj se dodává jako modul plug-in Visual Studio, nástroj příkazového řádkunebo zabalený do jednoduchého grafického uživatelského rozhraní, které zjednodušuje jeho možnosti. Další informace o použití analyzátoru přenositelnosti .NET (port rozhraní API) najdete v tomto příspěvku na blogu v tématu portování desktopových aplikací do .NET Core . Pokud dáváte přednost použití příkazového řádku, jsou nezbytné kroky:

  1. Stáhněte si analyzátor přenositelnosti .NET , pokud ho ještě nemáte.

  2. zajistěte, aby byla aplikace .NET Framework správně předaná sestavení (to je dobrý nápad před migrací bez ohledu na migraci).

  3. Spusťte port rozhraní API s příkazovým řádkem.

    ApiPort.exe analyze -f <PathToBeanTraderBinaries> -r html -r excel -t ".NET Core"
    

    -fArgument určuje cestu obsahující binární soubory, které se mají analyzovat. -rArgument určuje formát výstupního souboru, který chcete. -tArgument určuje, která platforma .NET bude analyzovat využití rozhraní API. V takovém případě chcete .NET Core.

Když otevřete sestavu HTML, v první části se zobrazí všechny analyzované binární soubory a procento používaných rozhraní API .NET, které jsou k dispozici na cílové platformě. Procento není smysluplné. Užitečnější je zobrazit konkrétní chybějící rozhraní API. Chcete-li to provést, buď vyberte název sestavení, nebo se posuňte dolů k sestavám pro jednotlivá sestavení.

Zaměřte se na sestavení, pro která vlastníte zdrojový kód. v sestavě ApiPorta v programu bob obchodník je například uveden mnoho binárních souborů, ale většina z nich patří do balíčků NuGet. Castle.Windsor ukazuje, že závisí na některých rozhraních API System. Web, které chybí v .NET Core. Nejedná se o problém, protože jste předtím ověřili, že Castle.Windsor produkt podporuje .NET Core. je běžné, že NuGet balíčky mají různé binární soubory pro použití s různými platformami .net, takže pokud je .NET Frameworká verze nástroje Castle.Windsor System. Web api nebo není relevantní, tak dlouho, dokud balíček cílí také na .NET Standard nebo .net Core (který dělá).

V případě ukázky pro obchodníka v programu Bob je jediným binárním souborem, který je třeba vzít v úvahu, BeanTraderClient a tato sestava uvádí, že chybí pouze dvě rozhraní API .NET: System.ServiceModel.ClientBase<T>.Close a System.ServiceModel.ClientBase<T>.Open .

Sestava přenositelnosti BeanTraderClient

Je pravděpodobné, že nebudou blokovat problémy, protože rozhraní API klienta WCF jsou v .NET Core podporována (většinou), takže pro tato centrální rozhraní API musí být k dispozici alternativní řešení. Ve skutečnosti se podívejte na System.ServiceModel oblast .NET Core Surface (pomocí https://apisof.net ), že místo toho jsou v .NET Core k dispozici asynchronní alternativy.

na základě této sestavy a předchozí analýzy závislostí NuGet vypadá to, že by nedocházelo k žádným významným problémům při migraci ukázkového obchodníka z části bob obchodník do .net Core. Jste připraveni na další krok, ve kterém bude migrace skutečně zahájena.

Migruje se soubor projektu.

Pokud vaše aplikace nepoužívá nový Formát souboru projektu ve stylu sady SDK, budete potřebovat nový soubor projektu pro cílové rozhraní .NET Core. Existující soubor CSPROJ můžete nahradit, nebo pokud upřednostňujete zachování existujícího projektu v jeho aktuálním stavu, můžete přidat nový soubor CSPROJ cílící na rozhraní .NET Core. můžete sestavit verze aplikace pro .NET Framework a .net Core s jedním souborem projektu ve stylu sady SDK s cílením na více verzí (určením více <TargetFrameworks> cílů).

chcete-li vytvořit nový soubor projektu, můžete vytvořit nový projekt WPF v Visual Studio nebo použít dotnet new wpf příkaz v dočasném adresáři pro vygenerování souboru projektu a potom jej zkopírovat nebo přejmenovat do správného umístění. K dispozici je také nástroj CsprojToVs2017vytvořený komunitou, který může automatizovat některé migrace souborů projektu. Tento nástroj je užitečný, ale ještě potřebuje člověk ke kontrole výsledků, aby se zajistilo, že všechny podrobnosti migrace jsou správné. jedna konkrétní oblast, kterou nástroj nezpracovává optimálně, migruje NuGet balíčky z packages.config souborů. je-li nástroj spuštěn v souboru projektu, který stále používá packages.config soubor pro odkaz NuGet balíčky, provede migraci na <PackageReference> prvky automaticky, ale přidá <PackageReference> prvky pro všechny balíčky místo pouze těch, které mají nejvyšší úroveň. pokud jste již migrovali na <PackageReference> prvky pomocí Visual Studio (jak jste to udělali v této ukázce), nástroj může pomáhat se zbytkem převodu. Podobně jako Scott Hanselman doporučuje ve svém blogovém příspěvku o migraci souborů csproj. přenos po ruce je vzdělávací a výsledkem je lepší výsledky, pokud máte pouze několik projektů na port. Pokud ale přenášíte desítky nebo stovky souborů projektu, může se jednat o nástroj, jako je CsprojToVs2017 .

Chcete-li vytvořit nový soubor projektu pro ukázku pro obchodní oddělení, spusťte příkaz dotnet new wpf v dočasném adresáři a přesuňte vygenerovaný soubor . csproj do složky BeanTraderClient a přejmenujte jej na BeanTraderClient. Core. csproj.

Vzhledem k tomu, že nový formát souboru projektu automaticky obsahuje soubory jazyka C#, soubory RESX a soubory XAML, které nalezne v nebo v jejím adresáři, je soubor projektu již skoro dokončen. Pro dokončení migrace otevřete staré a nové soubory projektu vedle sebe a Prohlédněte si starou a podívejte se, jestli je potřeba migrovat nějaké informace, které obsahuje. V ukázkovém případu pro hospodářský subjekt by měly být do nového projektu zkopírovány následující položky:

  • <RootNamespace> <AssemblyName> Všechny vlastnosti, a <ApplicationIcon> by měly být kopírovány.

  • Také je nutné přidat do <GenerateAssemblyInfo>false</GenerateAssemblyInfo> nového souboru projektu vlastnost, protože ukázka obchodní obchodník zahrnuje atributy na úrovni sestavení (například [AssemblyTitle] ) v souboru AssemblyInfo. cs. Ve výchozím nastavení budou nové projekty ve stylu sady SDK tyto atributy generovat na základě vlastností v souboru csproj. Vzhledem k tomu, že v tomto případě nechcete, aby k tomu docházelo (automaticky vygenerovaný atribut by byl v konfliktu s hodnotami z AssemblyInfo. cs), zakážete automaticky generované atributy pomocí <GenerateAssemblyInfo> .

  • I když soubory RESX jsou automaticky zahrnuty jako vložené prostředky, jiné <Resource> položky jako obrázky nejsou. Proto zkopírujte <Resource> prvky pro vkládání obrázků a souborů ikon. Můžete zjednodušit odkazy PNG na jeden řádek pomocí nového formátu souboru projektu, který je podporován pro vzory expanze názvů: <Resource Include="**\*.png" /> .

  • Podobně <None> jsou položky automaticky zahrnuty, ale ve výchozím nastavení nejsou zkopírovány do výstupního adresáře. Vzhledem k tomu, že projekt fazolového účastníka obsahuje <None> položku, která je zkopírována do výstupního adresáře (pomocí PreserveNewest chování), je třeba aktualizovat automaticky vyplněnou <None> položku pro tento soubor, například.

    <None Update="BeanTrader.pfx">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    
  • Ukázka pro obchodníka Bob zahrnuje soubor XAML (default. akcent. XAML) jako Content (nikoli jako), Page protože motivy a zvýraznění definované v tomto souboru jsou načteny z XAML souboru za běhu, místo aby se vložily do samotné aplikace. Nový projektový systém automaticky zahrne tento soubor jako <Page> , protože se jedná o soubor XAML. Proto je nutné soubor XAML odebrat jako stránku ( <Page Remove="**\Default.Accent.xaml" /> ) a přidat jej jako obsah.

    <Content Include="Resources\Themes\Default.Accent.xaml">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    
  • nakonec přidejte NuGet odkazy tak, že zkopírujete <ItemGroup> všechny <PackageReference> prvky. pokud jste jste dříve upgradovali balíčky NuGet na verze kompatibilní se standardem .net core, můžete to udělat, pokud jsou odkazy na balíček v projektu specifickém pro .net core.

V tomto okamžiku by mělo být možné přidat nový projekt do řešení BeanTrader a otevřít ho v Visual Studio. Projekt by měl vypadat správně v Průzkumník řešení a dotnet restore BeanTraderClient.Core.csproj měl by úspěšně obnovit balíčky (se dvěma očekávanými upozorněními souvisejícími s verzí MahApps. metro, kterou používáte cílení .NET Framework).

I když je možné uchovávat oba soubory projektu souběžně (a může to být žádoucí, pokud chcete zachovat původní projekt přesně tak, jak byl), ztěžuje proces migrace (tyto dva projekty se pokusí použít stejné složky bin a obj) a obvykle není nutné. pokud chcete sestavovat pro cíle .net Core i .NET Framework, můžete <TargetFramework>netcoreapp3.0</TargetFramework> místo toho nahradit vlastnost v novém souboru projektu <TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks> . V případě ukázky pro obchodní oddělení odstraňte starý soubor projektu (BeanTraderClient. csproj), protože už není potřeba. Pokud chcete zachovat oba soubory projektu, nezapomeňte je nechat sestavit do různých výstupních a zprostředkujících výstupních cest.

Opravit problémy sestavení

Třetí krok procesu přenosu získává projekt, který se má sestavit. Některé aplikace budou po převedení souboru projektu na projekt ve stylu sady SDK již sestaveny úspěšně. Pokud je to váš případ pro vaši aplikaci, Blahopřejeme! Můžete přejít ke kroku 4. Ostatní aplikace budou potřebovat nějaké aktualizace, aby je mohli sestavit pro .NET Core. pokud se pokusíte spustit dotnet build ukázkový projekt ve vzorci pro povýšení, například (nebo ho sestavit v Visual Studio), dojde k velkému počtu chyb, ale budete ho rychle potřebovat.

Odkazy na System. ServiceModel a Microsoft. Windows. Režim

Ve společném zdroji chyb chybí odkazy pro rozhraní API, která jsou k dispozici pro .NET Core, ale nejsou automaticky zahrnutá do aplikace .NET Core Metapackage. Pokud to chcete vyřešit, měli byste se na Microsoft.Windows.Compatibility balíček odkazovat. balíček kompatibility zahrnuje širokou škálu rozhraní api, která jsou společná pro Windows desktopové aplikace, jako je například klient WCF, adresářové služby, registr, konfigurace, rozhraní api seznamů acl a další.

V případě ukázky v programu Bob obchodník je většina chyb sestavení způsobena chybějícími System.ServiceModel typy. ty je možné řešit pomocí odkazů na potřebné balíčky NuGet WCF. Klientská rozhraní API WCF jsou mezi systémy přítomnými v Microsoft.Windows.Compatibility balíčku, a to i tak, aby odkazovaly na balíček kompatibility ještě lepším řešením (protože taky řeší všechny problémy související s rozhraními API a také řešení problémů, ke kterým balíček kompatibility zpřístupňuje přístup). Microsoft.Windows.CompatibilityBalíček pomáhá ve většině scénářů pro přenos rozhraní .NET Core 3,0 WPF a WinForms. po přidání odkazu NuGet do Microsoft.Windows.Compatibility , zůstane jenom jedna chyba buildu!

Čištění nepoužívaných souborů

Jeden typ problému migrace, který se často týká souborů C# a XAML, které nebyly dříve zahrnuty do sestavení, vybírají nové projekty ve stylu sady SDK, které zahrnují všechny zdroje automaticky.

Další chyba sestavení, kterou vidíte v ukázce pro obchodní vztah, odkazuje na chybnou implementaci rozhraní v OldUnusedViewModel. cs. Název souboru je pomocný parametr, ale při kontrole zjistíte, že tento zdrojový soubor není správný. nezpůsobila problémy dříve, protože neobsahovala původní .NET Framework projekt. Zdrojové soubory, které byly přítomny na disku, ale nejsou zahrnuté do starého souboru csproj , jsou teď zahrnuté automaticky.

V případě nedostatku problému se dá snadno porovnat s předchozími csproj a potvrdit, že soubor není potřeba, a pak <Compile Remove="" /> ho buď nebo, pokud už zdrojový soubor ještě není potřeba, odstranit. V tomto případě je bezpečné jenom odstranit OldUnusedViewModel. cs.

Pokud máte mnoho zdrojových souborů, které by musely být vyloučeny tímto způsobem, můžete zakázat automatické zahrnutí souborů jazyka C# nastavením <EnableDefaultCompileItems> vlastnosti na hodnotu false v souboru projektu. Pak můžete zkopírovat <Compile Include> položky ze starého souboru projektu do nového, aby bylo možné sestavit pouze zdroje, které mají být zahrnuty. Podobně <EnableDefaultPageItems> lze použít k vypnutí automatického zahrnutí stránek XAML a <EnableDefaultItems> může řídit jak jedinou vlastností.

Stručný výběr v kompilátorech s více průchody

Po odebrání problematického souboru z ukázky pro obchodníka z fazolového účastníka můžete znovu sestavit a zobrazí se čtyři chyby. Ještě nemáte nějaké předplatné? Proč počet chyb zachází? Kompilátor jazyka C# je Vícenásobný předávací kompilátor. To znamená, že každý zdrojový soubor projde dvakrát. Za prvé kompilátor pouze prohlíží metadata a deklarace v každém zdrojovém souboru a identifikuje všechny problémy na úrovni deklarace. Jedná se o chyby, které jste opravili. Poté provede kód znovu a sestaví zdroj C# do IL; Ty jsou druhou sadou chyb, které vidíte nyní.

Poznámka

Kompilátor jazyka C# provede více než pouze dva průchody, ale konečný výsledek je, že chyby kompilátoru pro velké změny kódu, jako by to vedlo k tomu, že jsou dva vlny.

Opravy závislostí třetích stran (Castle. Windsor)

další třídou problému, která se nachází v některých scénářích migrace, jsou rozdíly v rozhraní API mezi .NET Framework a verzemi závislostí .net Core. i v případě, že NuGet balíček cílí .NET Framework i .NET Standard i rozhraní .net Core, mohou existovat různé knihovny pro použití s různými cíli .net. Díky tomu mohou balíčky podporovat mnoho různých platforem .NET, které mohou vyžadovat různé implementace. Také to znamená, že při cílení na různé platformy .NET můžou knihovny obsahovat malé rozdíly v rozhraní API.

Další sada chyb, které vidíte v ukázce obchodníka v programu Bob, se vztahuje na Castle.Windsor rozhraní API. projekt .net Core bob používá stejnou verzi Castle.Windsor jako projekt cílený na .NET Framework (4.1.1), ale implementace těchto dvou platforem se mírně liší.

V takovém případě se zobrazí následující problémy, které je potřeba opravit:

  1. Castle.MicroKernel.Registration.Classes.FromThisAssembly není k dispozici v .NET Core. K dispozici je však podobné rozhraní API Classes.FromAssemblyContaining , takže můžeme nahradit obě použití Classes.FromThisAssembly() voláním Classes.FromAssemblyContaining(t) metody, kde t je typ, který provádí volání.
  2. Podobně v zaváděcím programu. cs, Castle.Windsor.Installer.FromAssembly . Tato technologie není v .NET Core dostupná. Místo toho lze toto volání nahradit pomocí FromAssembly.Containing(typeof(Bootstrapper)) .

Aktualizace využití klienta WCF

V případě, že jsou rozdíly vyřešeny Castle.Windsor , poslední zbývající chyba sestavení v projektu .NET Core Bob obchodník je, že BeanTraderServiceClient (která je odvozena z DuplexClientBase ) nemá Open metodu. To není překvapivé, protože se jedná o rozhraní API, které na začátku tohoto procesu migrace zvýrazní analyzátor přenositelnosti .NET. Podíváme BeanTraderServiceClient se na to, co se věnuje pozornost většímu problému, ale. Tento klient WCF byl automaticky vygenerován nástrojem Svcutil.exe .

Klienti WCF vygenerované službou Svcutil jsou určeny pro použití v .NET Framework.

Řešení, která používají Svcutil klienty WCF, budou muset znovu vygenerovat klienty kompatibilní s .NET Standard pro použití s .NET Core. Jedním z hlavních důvodů, proč původní klienti nebudou fungovat, jsou závislé na konfiguraci aplikací pro definování vazeb a koncových bodů WCF. Protože .NET Standard rozhraní API WCF můžou pracovat na různých platformách (kde nejsou k dispozici rozhraní API pro System. Configuration), klienti WCF pro scénáře .NET Core a .NET Standard musí definovat vazby a koncové body programově místo v konfiguraci.

Ve skutečnosti bude nutné změnit použití všech klientů WCF, které závisí na <system.serviceModel> app.config sekci (ať už vytvořené pomocí Svcutil nebo ručně), aby fungovaly v .NET Core.

Existují dva způsoby, jak automaticky generovat .NET Standard kompatibilních klientů WCF:

  • Tento dotnet-svcutil Nástroj je nástroj .NET, který generuje klienty WCF způsobem, který je podobný tomu, jak Svcutil pracovali dříve.
  • Visual Studio může generovat klienty WCF pomocí možnosti WCF Web Service Reference funkce připojené služby.

Oba postupy fungují dobře. Můžete samozřejmě napsat kód klienta WCF sami. v této ukázce se používá funkce Visual Studio připojené služby. provedete to tak, že kliknete pravým tlačítkem na projekt BeanTraderClient. Core v průzkumníku řešení Visual Studio a vyberete přidat > připojenou službu. v dalším kroku vyberte poskytovatele WCF Web Service Reference. Tím se zobrazí dialogové okno, kde můžete zadat adresu webové služby back-end účastníka (Pokud používáte localhost:8080 Server místně) a obor názvů, který mají generované typy použít (například BeanTrader. Service).

WCF Web Service Reference Dialogové okno připojené služby

Po výběru tlačítka Dokončit se do projektu přidá nový uzel připojené služby a do něj se přidá soubor reference. cs, který obsahuje nový .NET Standard klienta WCF pro přístup ke službě bobů obchodník. Pokud se podíváte GetEndpointAddress na GetBindingForEndpoint metody nebo v tomto souboru, uvidíte, že vazby a koncové body se nyní generují programově (místo pomocí konfigurace aplikace). Funkce přidat připojené služby může také přidat odkazy na některé balíčky System. ServiceModel v souboru projektu, které nejsou potřeba, protože všechny potřebné balíčky WCF jsou zahrnuté přes Microsoft. Windows. Režim. Zkontrolujte csproj a podívejte se, jestli se přidaly další položky System. ServiceModel <PackageReference> , a pokud ano, odeberte je.

Náš projekt má nyní nové třídy klienta WCF (v referenci. cs), ale stále obsahuje staré (v BeanTrader. cs). V tuto chvíli jsou k dispozici dvě možnosti:

  • pokud chcete mít možnost sestavit původní .NET Framework projekt (společně s novým cílem rozhraní .net core), můžete použít <Compile Remove="BeanTrader.cs" /> položku v souboru csproj projektu .net core tak, aby .NET Framework a verze .net core aplikace používaly různé klienty WCF. tato výhoda má opustit stávající projekt .NET Framework beze změny, ale má nevýhodu, že kód pomocí generovaných klientů WCF může být v případě .net Core v případě, že je v projektu .NET Framework, trochu odlišný, takže pravděpodobně budete muset použít #if direktivy k podmíněně zkompilování některých využití klientů wcf (vytváření klientů, například), aby fungovaly jedním ze způsobů, jak je sestaven pro .net Core, a jiný způsob, jak je sestaven pro .NET Framework.

  • pokud je naopak některé změny kódu v existujícím projektu .NET Framework přijatelné, můžete BeanTrader. cs odebrat dohromady. vzhledem k tomu, že nový klient služby WCF je sestaven pro .NET Standard, bude fungovat ve scénářích .net Core i .NET Framework. pokud sestavíte pro .NET Framework kromě .net Core (buď pomocí cílení na více platforem, nebo se dvěma soubory csproj), můžete použít tento nový soubor Reference. cs pro oba cíle. Tento přístup má výhodu, že kód nemusí bifurcate k podpoře dvou různých klientů WCF. stejný kód bude použit všude. nevýhodou je, že zahrnuje změnu (předpokládaně stabilní) .NET Framework projektu.

V případě ukázky programu Bob obchodník můžete v původním projektu provést drobné změny, pokud to usnadňuje migraci, takže pomocí těchto kroků sjednotete použití klientů WCF:

  1. přidejte nový soubor Reference. cs do projektu .NET Framework BeanTraderClient. csproj pomocí kontextové nabídky přidat existující položku z průzkumníka řešení. Nezapomeňte přidat "as Link", aby oba projekty používaly stejný soubor (na rozdíl od kopírování souboru v jazyce C#). pokud vytváříte rozhraní .net Core i .NET Framework s jedním csproj (pomocí cílení na více platforem), tento krok není nezbytný.

  2. Odstraňte BeanTrader. cs.

  3. Nový klient služby WCF je podobný původnímu, ale několik oborů názvů v generovaném kódu se liší. Z tohoto důvodu je nutné aktualizovat projekt tak, aby se typy klientů WCF používaly ze služby BeanTrader. Service (nebo libovolného názvu oboru názvů, který jste zvolili) místo BeanTrader. model nebo bez oboru názvů. Sestavování BeanTraderClient. Core. csproj vám pomůže zjistit, kde se tyto změny musí provést. Opravy budou potřeba v C# i ve zdrojových souborech XAML.

  4. Nakonec zjistíte, že v BeanTraderServiceClientFactory. cs dojde k chybě, protože se změnily dostupné konstruktory pro daný BeanTraderServiceClient typ. Slouží k zadání InstanceContext argumentu (který byl vytvořen pomocí CallbackHandler z Castle.Windsor kontejneru IOC). Nové konstruktory vytvoří nové CallbackHandler s. Existují však konstruktory v BeanTraderServiceClient základním typu, které odpovídají požadovaným požadavkům. Vzhledem k tomu, že automaticky generovaný kód klienta WCF existuje v dílčích třídách, je možné jej snadno zvětšit. Provedete to tak, že vytvoříte nový soubor s názvem BeanTraderServiceClient. cs a pak vytvoříte částečnou třídu se stejným názvem (pomocí oboru názvů BeanTrader. Service). Pak přidejte jeden konstruktor na částečný typ, jak je znázorněno zde.

    public BeanTraderServiceClient(System.ServiceModel.InstanceContext callbackInstance) :
        base(callbackInstance, EndpointConfiguration.NetTcpBinding_BeanTraderService)
            { }
    

Po provedení těchto změn teď bude ukázka pro obchodníka v programu Bob používat nového klienta WCF kompatibilního s .NET Standard a můžete provést konečnou opravu změny Open volání v souboru TradingService. cs , aby se await OpenAsync místo toho použila.

S vyřešenými problémy WCF se nyní sestavuje verze .NET Core ukázkového obchodníka v programu Bob.

Testování za běhu

Je snadné se zapomenout, že migrace se neprovádí ihned po vyčištění sestavení projektu proti .NET Core. Je důležité, abyste ponechali čas při testování portu aplikace. Jakmile se všechno úspěšně sestaví, ujistěte se, že aplikace běží a funguje podle očekávání, zvlášť pokud používáte jakékoliv balíčky cílené .NET Framework.

Pojďme se pokusit spustit aplikaci s portem pro obchodní informování a zjistit, co se stane. Aplikace se před selháním nezdaří s následující výjimkou.

System.Configuration.ConfigurationErrorsException: 'Configuration system failed to initialize'

Inner Exception
ConfigurationErrorsException: Unrecognized configuration section system.serviceModel.

To samozřejmě dává smysl. Mějte na paměti, že WCF už nepoužívá konfiguraci aplikace, takže původní oddíl System. serviceModel souboru app.config musí být odebraný. Aktualizovaný klient služby WCF zahrnuje všechny stejné informace ve svém kódu, takže konfigurační oddíl už není potřeba. Pokud jste chtěli nakonfigurovat koncový bod WCF v app.config, můžete ho přidat jako nastavení aplikace a aktualizovat kód klienta WCF pro načtení koncového bodu služby WCF z konfigurace.

Po odebrání oddílu System. serviceModel v app.config se aplikace spustí, ale při přihlášení uživatele dojde k chybě s jinou výjimkou.

System.PlatformNotSupportedException: 'Operation is not supported on this platform.'

Nepodporované rozhraní API je Func<T>.BeginInvoke . Jak je vysvětleno v dotnet/corefx # 5940, .NET Core nepodporuje BeginInvoke EndInvoke metody a na typech delegátů z důvodu základních závislostí vzdálené komunikace. Tento problém a jeho opravu jsou podrobněji popsány v článku migrace delegáta. BeginInvoke volání pro Blogový příspěvek .NET Core, ale v registru je to, že BeginInvoke Pokud je EndInvoke to možné, by volání měla být nahrazena Task.Run (nebo asynchronními alternativami). Když použijete obecné řešení, BeginInvoke volání se dá nahradit Invoke voláním spuštěným v Task.Run .

Task.Run(() =>
{
    return userInfoRetriever.Invoke();
}).ContinueWith(result =>
{
    // BeginInvoke's callback is replaced with ContinueWith
    var task = result.ConfigureAwait(false);
    CurrentTrader = task.GetAwaiter().GetResult();
}, TaskScheduler.Default);

Po odebrání BeginInvoke použití se aplikace Bob obchodník úspěšně spustí pro .NET Core.

Obchodník pro fazole běžící v .NET Core

Všechny aplikace se liší, takže konkrétní kroky potřebné k migraci vlastních aplikací do .NET Core se budou lišit. Ale snad v ukázce Bob obchodník ukazuje obecný pracovní postup a typy problémů, které je možné očekávat. A i přes délku tohoto článku se skutečné změny potřebné v ukázce pro obchodníka v rámci nástroje Bob, aby fungovaly v .NET Core, byly poměrně omezené. Mnoho aplikací migruje do .NET Core stejným způsobem; s omezením nebo dokonce bez nutnosti změn kódu.