Generování projekce jazyka C# z komponenty C++/WinRT, která se distribuuje jako NuGet pro .NET aplikace

V tomto tématu se naučíme, jak použít C#/WinRT k vygenerování sestavení pro interoperabilitu .NET v jazyce C# z komponenty prostředí Windows Runtime C++/WinRT a jak ho distribuovat jako balíček NuGet pro .NET aplikace.

Od .NET 6 se již nepodporuje použití souborů metadat Windows (WinMD) (viz Vestavěná podpora pro WinRT byla odebrána z .NET). Místo toho lze nástroj C#/WinRT použít k vygenerování sestavení projekce pro libovolný soubor WinMD, který pak umožňuje spotřebu komponent WinRT z .NET aplikací. Sestavení projekce je také známé jako interoperabilní sestavení. V tomto názorném postupu se dozvíte, jak postupovat následovně:

  • Pomocí balíčku C#/WinRT vygenerujte projekce jazyka C# z komponenty C++/WinRT.
  • Distribuujte komponentu spolu se sestavením projekce jako balíček NuGet.
  • Využití balíčku NuGet z konzolové aplikace .NET

Požadavky

Tento názorný postup a odpovídající ukázka vyžadují následující nástroje a komponenty:

  • Visual Studio 2022 nebo novější s nainstalovanou úlohou vývoje Univerzální platforma Windows. V Podrobnosti o instalaci>vývoj Univerzální platformy Windows zkontrolujte možnost nástroje C++ (v14x) pro Univerzální platformu Windows.
  • .NET 8.0 SDK (LTS) nebo novější.

V tomto názorném postupu budeme používat Visual Studio 2022 nebo novější a .NET 8.

Důležité

Také budete muset stáhnout nebo naklonovat ukázkový kód pro toto téma z projekce C#/WinRT na GitHub. Přejděte na CsWinRT a kliknutím na zelené tlačítko Kód získejte git clone adresu URL. Nezapomeňte si pro ukázku přečíst soubor README.md .

Vytvoření jednoduché komponenty C++/WinRT prostředí Windows Runtime

Abyste mohli postupovat podle tohoto návodu, musíte mít nejprve komponentu C++/WinRT prostředí Windows Runtime (WRC), ze které chcete vygenerovat sestavení projekce jazyka C#.

Tento návod používá SimpleMathComponent WRC z ukázky C#/WinRT projekce na GitHubu, kterou jste si už stáhli nebo naklonovali. SimpleMathComponent byl vytvořen ze šablony projektu prostředí Windows Runtime (C++/WinRT) Visual Studio.

Pokud chcete otevřít projekt SimpleMathComponent v Visual Studio, otevřete soubor \CsWinRT\src\Samples\NetProjectionSample\CppWinRTComponentProjectionSample.sln, který najdete ve stažení nebo klonu úložiště.

Kód v tomto projektu poskytuje funkce základních matematických operací zobrazených v níže uvedeném souboru hlaviček.

// SimpleMath.h
...
namespace winrt::SimpleMathComponent::implementation
{
    struct SimpleMath: SimpleMathT<SimpleMath>
    {
        SimpleMath() = default;
        double add(double firstNumber, double secondNumber);
        double subtract(double firstNumber, double secondNumber);
        double multiply(double firstNumber, double secondNumber);
        double divide(double firstNumber, double secondNumber);
    };
}

Můžete potvrdit, že je vlastnost Windows Desktop Compatible nastavená na Yes pro projekt komponent SimpleMathComponent C++/WinRT prostředí Windows Runtime komponent. Provedete to tak, že ve vlastnostech project pro SimpleMathComponent, v části Vlastnosti konfigurace>General>Project Defaults, Nastavte vlastnost Windows Desktop Compatible na Yes. Tím se zajistí načtení správných binárních souborů modulu runtime pro využívání .NET desktopových aplikací.

stránka vlastností kompatibilní s plochou

Podrobnější postupy vytvoření komponenty C++/WinRT a generování souboru WinMD najdete v prostředí Windows Runtime komponenty C++/WinRT.

Poznámka:

Pokud implementujete IInspectable::GetRuntimeClassName ve své komponentě, musí vrátit platný název třídy WinRT. Vzhledem k tomu, že jazyk C#/WinRT používá řetězec názvu třídy pro interoperabilitu, nesprávný název runtime třídy vyvolá výjimku InvalidCastException.

Přidání projektu projekce do řešení komponent

Nejprve, když je řešení CppWinRTComponentProjectionSample stále otevřené ve Visual Studio, odeberte projekt SimpleMathProjection z řešení. Potom odstraňte ze systému souborů složku SimpleMathProjection (nebo ji přejmenujte, pokud chcete). Tyto kroky jsou nezbytné, abyste mohli postupovat podle tohoto podrobného návodu.

  1. Přidejte do svého řešení nový projekt knihovny C#.

    1. V Průzkumník řešení klikněte pravým tlačítkem na uzel řešení a klikněte na Přidat>Nový Project.
    2. V dialogovém okně Přidat nový projekt zadejte do vyhledávacího pole Knihovna tříd. V seznamu jazyků zvolte C# a pak v seznamu platforem zvolte Windows. Zvolte šablonu projektu jazyka C#, která se nazývá jednoduše knihovna tříd (bez předpon ani přípon) a klikněte na tlačítko Další.
    3. Pojmenujte nový projekt SimpleMathProjection. Umístění by již mělo být nastaveno na stejnou \CsWinRT\src\Samples\NetProjectionSample složku, ve které je složka SimpleMathComponent , ale potvrďte to. Pak klikněte na tlačítko Další.
    4. Na stránce Přidatné informace vyberte .NET 8.0 (Dlouhodobá podpora) a pak zvolte Create.
  2. Odstraňte zástupný Class1.cs soubor z projektu.

  3. Pomocí následujícího postupu nainstalujte balíček NuGet C#/WinRT.

    1. V Průzkumník řešení klikněte pravým tlačítkem na projekt SimpleMathProjection a vyberte Manage NuGet Packages.
    2. Na kartě Browse zadejte nebo vložte Microsoft.Windows. CsWinRT do vyhledávacího pole, ve výsledcích hledání vyberte položku s nejnovější verzí a potom kliknutím na Install nainstalujte balíček do projektu SimpleMathProjection.
  4. Přidejte do SimpleMathProjection odkaz na projekt SimpleMathComponent . V Průzkumník řešení klikněte pravým tlačítkem na uzel Dependencies pod uzlem SimpleMathProjection project, vyberte Přidat Project Reference a vyberte SimpleMathComponent project >OK.

Zatím se nepokoušejte sestavit projekt. Uděláme to v pozdějším kroku.

Zatím by vaše Průzkumník řešení měla vypadat nějak takto (vaše čísla verzí se budou lišit).

Průzkumník řešení zobrazující závislosti projekčního projektu

Vytváření projektů mimo zdroj

Pro řešení CppWinRTComponentProjectionSample v ukázce projekce C#/WinRT (které jste stáhli nebo naklonovali z GitHubu, a teď máte otevřené) je výstupní umístění sestavení nakonfigurováno pomocí souboru Directory.Build.props pro sestavování mimo zdrojový adresář. To znamená, že soubory z výstupu sestavení se generují mimo zdrojové složky. Pokud používáte nástroj C#/WinRT, doporučujeme vytvořit ho ze zdroje. To brání kompilátoru jazyka C# neúmyslně vyzvednout všechny soubory *.cs v kořenovém adresáři projektu, což může způsobit chyby duplicitního typu (například při kompilaci pro více konfigurací a/nebo platforem).

I když je to už nakonfigurované pro řešení CppWinRTComponentProjectionSample , postupujte podle následujících kroků a vyzkoušejte si konfiguraci sami.

Nakonfigurujte své řešení pro sestavení mimo zdroj:

  1. Když je řešení CppWinRTComponentProjectionSample stále otevřené, klikněte pravým tlačítkem myši na uzel řešení a vyberte Přidat>Novou položku. Vyberte položku soubor XML a pojmenujte ji Directory.Build.props (bez přípony .xml ). Chcete-li přepsat existující soubor, klikněte na tlačítko Ano .

  2. Obsah adresáře.Build.props nahraďte konfigurací níže.

    <Project>
      <PropertyGroup>
        <BuildOutDir>$([MSBuild]::NormalizeDirectory('$(SolutionDir)', '_build', '$(Platform)', '$(Configuration)'))</BuildOutDir>
        <OutDir>$([MSBuild]::NormalizeDirectory('$(BuildOutDir)', '$(MSBuildProjectName)', 'bin'))</OutDir>
        <IntDir>$([MSBuild]::NormalizeDirectory('$(BuildOutDir)', '$(MSBuildProjectName)', 'obj'))</IntDir>
      </PropertyGroup>
    </Project>
    
  3. Uložte a zavřete soubor Directory.Build.props .

Úprava souboru projektu pro spuštění C#/WinRT

Než budete moci vyvolat cswinrt.exe nástroj pro generování sestavení projekce, musíte nejprve upravit soubor projektu a zadat několik vlastností projektu.

  1. V Průzkumník řešení poklikejte na uzel SimpleMathProjection a otevřete soubor projektu v editoru.

  2. Aktualizujte element TargetFramework tak, aby cílil na konkrétní verzi sady WINDOWS SDK. Tím se přidají závislosti sestavení, které jsou nezbytné pro podporu interoperability a projekce. Tato ukázka cílí na Windows SDK verze net6.0-windows10.0.19041.0 (označovaná také jako Windows 10, verze 2004). Nastavte prvek Platform na AnyCPU tak, aby výsledné sestavení projekce bylo možné použít v architektuře jakékoli aplikace. Pokud chcete povolit odkazování aplikací na podporu starších verzí sady WINDOWS SDK, můžete také nastavit vlastnost TargetPlatformMinimumVersion.

    <PropertyGroup>
      <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
      <!-- Set Platform to AnyCPU to allow consumption of the projection assembly from any architecture. -->
      <Platform>AnyCPU</Platform>
    </PropertyGroup>
    

    Poznámka:

    Pro účely tohoto názorného postupu a souvisejícího ukázkového kódu je řešení sestavené pro platformu x64 a release. Všimněte si, že projekt SimpleMathProjection je nakonfigurovaný tak, aby se sestavoval pro AnyCPU pro všechny konfigurace architektury řešení.

  3. Přidejte druhý PropertyGroup prvek (bezprostředně za první), který nastaví několik vlastností C#/WinRT.

    <PropertyGroup>
      <CsWinRTIncludes>SimpleMathComponent</CsWinRTIncludes>
      <CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
    </PropertyGroup>
    

    Tady je několik podrobností o nastaveních v tomto příkladu:

    • Vlastnost CsWinRTIncludes určuje, které obory názvů se mají projektovat.
    • Vlastnost CsWinRTGeneratedFilesDir nastaví výstupní adresář, ve kterém jsou generovány zdrojové soubory projekce. Tato vlastnost je nastavena na OutDir, definován v Directory.Build.props z výše uvedené části.
  4. Uložte a zavřete soubor SimpleMathProjection.csproj a klikněte na Znovu načíst projekty v případě potřeby.

Vytvoření balíčku NuGet s projekcí

Pokud chcete distribuovat sestavení projekce pro vývojáře .NET aplikací, můžete při sestavování řešení automaticky vytvořit balíček NuGet přidáním dalších vlastností projektu. Pro cíle .NET musí balíček NuGet obsahovat sestavení projekce a sestavení implementace ze komponenty.

  1. Pomocí následujícího postupu přidejte do projektu .nuspec soubor specifikace NuGet ().

    1. V Průzkumník řešení, Klikněte pravým tlačítkem na uzel SimpleMathProjection, zvolte Add>New Folder a pojmenujte složku nuget.
    2. Klikněte pravým tlačítkem myši na složku NuGet , zvolte Přidat>novou položku, zvolte soubor XML a pojmenujte ji SimpleMathProjection.nuspec.
  2. V Průzkumník řešení poklikejte na uzel SimpleMathProjection a otevřete soubor projektu v editoru. Přidejte následující skupinu vlastností do nyní otevřené simpleMathProjection.csproj (hned za dva existující PropertyGroup prvky), aby se balíček automaticky vygeneroval. Tyto vlastnosti určují NuspecFile a adresář, ve kterém se má vygenerovat balíček NuGet.

    <PropertyGroup>
      <GeneratedNugetDir>.\nuget\</GeneratedNugetDir>
      <NuspecFile>$(GeneratedNugetDir)SimpleMathProjection.nuspec</NuspecFile>
      <OutputPath>$(GeneratedNugetDir)</OutputPath>
      <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    </PropertyGroup>
    

    Poznámka:

    Pokud dáváte přednost samostatnému generování balíčku, můžete se také rozhodnout spustit nástroj nuget.exe z příkazového řádku. Další informace o vytvoření balíčku NuGet najdete v tématu Vytvoření balíčku pomocí rozhraní příkazového řádku nuget.exe.

  3. Otevřete soubor SimpleMathProjection.nuspec pro úpravu vlastností vytváření balíčku a vložte následující kód. Níže uvedený fragment kódu je příkladem specifikace NuGet pro distribuci SimpleMathComponent do více cílových architektur. Všimněte si, že sestavení projekce SimpleMathProjection.dllje specifikováno namísto SimpleMathComponent.winmd pro cíl lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll. Toto chování je v .NET 6 a novějších novinkách a je povoleno jazykem C#/WinRT. Sestavení implementace SimpleMathComponent.dllmusí být také distribuováno a bude načteno za běhu.

    <?xml version="1.0" encoding="utf-8"?>
    <package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
      <metadata>
        <id>SimpleMathComponent</id>
        <version>0.1.0-prerelease</version>
        <authors>Contoso Math Inc.</authors>
        <description>A simple component with basic math operations</description>
        <dependencies>
          <group targetFramework="net6.0-windows10.0.19041.0" />
          <group targetFramework=".NETCoreApp3.0" />
          <group targetFramework="UAP10.0" />
          <group targetFramework=".NETFramework4.6" />
        </dependencies>
      </metadata>
      <files>
        <!--Support .NET 6, .NET Core 3, UAP, .NET Framework 4.6, C++ -->
        <!--Architecture-neutral assemblies-->
        <file src="..\..\_build\AnyCPU\Release\SimpleMathProjection\bin\SimpleMathProjection.dll" target="lib\net6.0-windows10.0.19041.0\SimpleMathProjection.dll" />
        <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\netcoreapp3.0\SimpleMathComponent.winmd" />
        <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\uap10.0\SimpleMathComponent.winmd" />
        <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.winmd" target="lib\net46\SimpleMathComponent.winmd" />
        <!--Architecture-specific implementation DLLs should be copied into RID-relative folders-->
        <file src="..\..\_build\x64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-x64\native\SimpleMathComponent.dll" />
        <!--To support x86 and Arm64, build SimpleMathComponent for those other architectures and uncomment the entries below.-->
        <!--<file src="..\..\_build\Win32\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-x86\native\SimpleMathComponent.dll" />-->
        <!--<file src="..\..\_build\arm64\Release\SimpleMathComponent\bin\SimpleMathComponent\SimpleMathComponent.dll" target="runtimes\win10-arm64\native\SimpleMathComponent.dll" />-->
      </files>
    </package>
    

    Poznámka:

    SimpleMathComponent.dll, sestavení implementace pro komponentu, je specifické pro architekturu. Pokud podporujete jiné platformy (například x86 nebo Arm64), musíte nejprve sestavit SimpleMathComponent pro požadované platformy a přidat tyto soubory sestavení do příslušné složky relativního identifikátoru RID. Sestavení projekce SimpleMathProjection.dll a komponenta SimpleMathComponent.winmd jsou obě architektury neutrální.

  4. Uložte a zavřete soubory, které jste právě upravili.

Sestavení řešení pro vygenerování projekce a balíčku NuGet

Před vytvořením řešení zkontrolujte nastavení Správce konfigurace v části Visual Studio v části Build>Správce konfigurace. Pro účely tohoto návodu nastavte Konfiguraci na Release a Platformu na x64 pro řešení.

V tuto chvíli můžete sestavit řešení. Klikněte pravým tlačítkem myši na uzel řešení a vyberte Sestavit řešení. Tím se nejprve sestaví projekt SimpleMathComponent a pak projekt SimpleMathProjection . Komponenta WinMD a implementační sestavení (SimpleMathComponent.winmd a SimpleMathComponent.dll), zdrojové soubory projekce a sestavení projekce (SimpleMathProjection.dll), budou všechny vygenerovány v adresáři výstupu _build. Ve složce \SimpleMathProjection\nuget také uvidíte vygenerovaný balíček NuGet SimpleMathComponent0.1.0-prerelease.nupkg.

Důležité

Pokud některý z výše uvedených souborů nebyl vygenerován, sestavte řešení ještě jednou. Před opětovným sestavením možná budete muset řešení zavřít a znovu otevřít.

Možná budete muset řešení zavřít a znovu otevřít, aby se .nupkg zobrazoval v Visual Studio, jak je znázorněno (nebo jednoduše vyberte a potom zrušte výběr Show All Files).

Průzkumník řešení zobrazující generování projekce

Odkazovat na balíček NuGet v konzolové aplikaci vytvořené v rámci C# .NET 6.

Pokud chcete využívat SimpleMathComponent z projektu .NET, můžete jednoduše přidat do nového projektu .NET odkaz na SimpleMathComponent0.1.0-prerelease.nupkg balíček NuGet, který jsme vytvořili v předchozí části. Následující kroky ukazují, jak to provést vytvořením jednoduché konzolové aplikace v samostatném řešení.

  1. Pomocí následujícího postupu vytvořte nové řešení obsahující projekt konzolové aplikace jazyka C# (vytvoření tohoto projektu v novém řešení umožňuje nezávisle obnovit balíček NuGet SimpleMathComponent ).

    Důležité

    Tento nový projekt konzolové aplikace vytvoříme uvnitř \CsWinRT\src\Samples\NetProjectionSample složky, kterou najdete ve stažené nebo klonované ukázce projekce C#/WinRT.

    1. V nové instanci Visual Studio vyberte Soubor>Nový>Projekt.
    2. V dialogovém okně Vytvořit nový projekt vyhledejte šablonu projektu konzolové aplikace . Zvolte šablonu projektu C#, která se nazývá jednoduše konzolová aplikace (bez předpon ani přípon), a klikněte na Další. Pokud používáte Visual Studio 2019, šablona projektu je Konsole Application.
    3. Pojmenujte nový projekt SampleConsoleApp, nastavte jeho umístění na stejnou \CsWinRT\src\Samples\NetProjectionSample složku, ve které jsou složky SimpleMathComponent a SimpleMathProjection , a klepněte na tlačítko Další.
    4. Na stránce Přidatné informace vyberte .NET 8.0 (Dlouhodobá podpora) a pak zvolte Create.
  2. V Průzkumník řešení dvojitým kliknutím na uzel SampleConsoleApp otevřete soubor projektu SampleConsoleApp.csproj, a upravte vlastnosti TargetFramework a Platform podle následujícího výpisu. Přidejte prvek Platform, pokud tam není.

    <PropertyGroup>
      <OutputType>Exe</OutputType>
      <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
      <Platform>x64</Platform>
    </PropertyGroup>
    
  3. Se souborem projektu SampleConsoleApp.csproj stále otevřeným, přidáme do projektu SampleConsoleApp odkaz na NuGet balíček SimpleMathComponent. Pokud chcete obnovit SimpleMathComponent NuGet při sestavování projektu, můžete použít RestoreSources vlastnost s cestou ke složce nuget v řešení komponent. Zkopírujte následující konfiguraci a vložte ji do SampleConsoleApp.csproj (uvnitř elementu Project).

    <PropertyGroup>
      <RestoreSources>
        https://api.nuget.org/v3/index.json;
        ../SimpleMathProjection/nuget
      </RestoreSources>
    </PropertyGroup>
    
    <ItemGroup>
      <PackageReference Include="SimpleMathComponent" Version="0.1.0-prerelease" />
    </ItemGroup>
    

    Důležité

    Cesta pro balíček SimpleMathComponent je nastavená na . Tato cesta je správná, pokud jste postupovali podle kroků v tomto návodu, aby projekty SimpleMathComponent a SampleConsoleApp byly ve stejné složce ( NetProjectionSample v tomto případě složka). Pokud jste udělali něco jiného, budete muset tuto cestu odpovídajícím způsobem upravit. Alternativně můžete do svého řešení přidat místní informační kanál balíčků NuGet.

  4. Upravte soubor Program.cs tak, aby používal funkce, které poskytuje SimpleMathComponent.

    var x = new SimpleMathComponent.SimpleMath();
    Console.WriteLine("Adding 5.5 + 6.5 ...");
    Console.WriteLine(x.add(5.5, 6.5).ToString());
    
  5. Uložte a zavřete soubory, které jste právě upravili, a sestavte a spusťte konzolovou aplikaci. Měl by se zobrazit následující výstup.

    výstup Console NET5

Známé problémy

  • Při sestavování projektu projekce se může zobrazit chyba jako: Chyba MSB3271: Došlo k neshodě mezi architekturou procesoru projektu, který se sestavuje, "MSIL", a architekturou procesoru "x86" souboru implementace "..\SimpleMathComponent.dll" pro "..\SimpleMathComponent.winmd". Tato neshoda může způsobit selhání za běhu. Zvažte změnu cílové architektury procesoru projektu prostřednictvím nástroje Správce konfigurace tak, abyste sladili architektury procesorů mezi vaším projektem a souborem implementace, nebo zvolte winmd soubor s implementačním souborem, který má architekturu procesoru odpovídající cílové architektuře procesoru vašeho projektu. K obejití této chyby přidejte následující vlastnost do souboru projektu knihovny jazyka C#:
    <PropertyGroup>
        <!-- Workaround for MSB3271 error on processor architecture mismatch -->
        <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
    </PropertyGroup>
    

Další aspekty

Sestavení projekce jazyka C# (nebo interop), které jsme ukázali, jak v tomto tématu vytvořit, je poměrně jednoduché – nemá závislosti na jiných komponentách. Pokud ale chcete vygenerovat projekce jazyka C# pro komponentu C++/WinRT s odkazy na typy Windows App SDK, musíte v projektu projekce přidat odkaz na balíček NuGet Windows App SDK. Pokud nějaké takové odkazy chybí, zobrazí se chyby jako "Typ <T> nelze nalézt".

Další věcí, kterou v tomto tématu děláme, je distribuce projekce jako balíčku NuGet. Tento je v současné době nezbytný.

Prostředky