Condividi tramite


Creazione di un componente Windows Runtime C# da usare da un'app C++/WinRT

Questo argomento illustra il processo di aggiunta di un semplice componente C# al vostro progetto C++/WinRT.

Visual Studio semplifica la creazione e la distribuzione di tipi Windows Runtime personalizzati all'interno di un progetto WRC (Windows Runtime Component) scritto con C# o Visual Basic e quindi di fare riferimento a tale WRC da un progetto di applicazione C++ e di utilizzare tali tipi personalizzati da tale applicazione.

Internamente, i tipi di Windows Runtime possono utilizzare qualsiasi funzionalità .NET consentita in un'applicazione UWP.

Esternamente, i membri del tipo possono esporre solo tipi di per i relativi parametri e valori restituiti. Quando si costruisce la soluzione, Visual Studio costruisce il progetto .NET WRC e poi esegue una fase di compilazione che crea un file di metadati di Windows (.winmd). Si tratta del componente di incluso nell'app da Visual Studio.

Nota

.NET mappa automaticamente alcuni tipi .NET comunemente usati, come i tipi di dati primitivi e i tipi di collezione, ai loro equivalenti di Windows Runtime. Questi tipi .NET possono essere utilizzati nell'interfaccia pubblica di un componente Windows Runtime e appariranno agli utenti del componente come i corrispondenti tipi Windows Runtime. Componenti Windows Runtime con C# e Visual Basic.

Prerequisiti

Crea un'app vuota

In Visual Studio crea un nuovo progetto usando il modello App vuota (C++/WinRT). Verifica che il modello usato sia (C++/WinRT) e non (Windows universale).

Impostare il nome del nuovo progetto su CppToCSharpWinRT in modo che la struttura di cartelle corrisponda alla procedura dettagliata.

Aggiungere un componente Windows Runtime C# alla soluzione

In Visual Studio, creare il progetto del componente: In Solution Explorer, aprite il menu di scelta rapida della soluzioneCppToCSharpWinRT e scegliete Add, quindi scegliete New Project per aggiungere un nuovo progetto C# alla soluzione. Nella sezione Installed Templates della finestra di dialogo Add New Project, scegliere Visual C#, quindi scegliere Windows, quindi Universal. Scegliere il modello Windows Runtime Component (Universal Windows) e inserireSampleComponent come nome del progetto.

Nota

Nella finestra di dialogo New Universal Windows Platform Project scegliere Windows 10 Creators Update (10.0; Build 15063) come versione minima. Per altre informazioni, vedere la sezione Application Minimum Version di seguito.

Aggiungere il metodo C# GetMyString

Nel progetto SampleComponent modificare il nome della classe da Class1 a Esempio. Aggiungere quindi due membri semplici alla classe, un campo int privato e un metodo di istanza denominato GetMyString:

    public sealed class Example
    {
        int MyNumber;

        public string GetMyString()
        {
            return $"This is call #: {++MyNumber}";
        }
    }

Nota

Per impostazione predefinita, la classe è contrassegnata public sealed. Tutte le classi di esposte dal componente devono essere sealed.

Nota

Facoltativo: per abilitare IntelliSense per i membri appena aggiunti, in Esplora soluzioni apri il menu di scelta rapida del progetto SampleComponent e scegli Build.

Fare riferimento a C# SampleComponent dal progetto CppToCSharpWinRT

In Esplora soluzioni, nel progetto JavaScript apri il menu di scelta rapida per References, dunque scegli Add Reference per aprire la finestraAdd Reference. Scegli Progetti, dunque scegli Soluzione. Seleziona la casella di controllo per il progetto SampleComponent e scegli OK per aggiungere un riferimento.

Nota

Opzionale: Per abilitare IntelliSense per il progetto C++/WinRT, in Solution Explorer aprite il menu di scelta rapida per il progetto CppToCSharpWinRT e scegliete Build.

Modificare MainPage.h

Aprire MainPage.h nel progetto CppToCSharpWinRT e quindi aggiungere due elementi. Aggiungere prima #include "winrt/SampleComponent.h" alla fine delle istruzioni #include, quindi un campo winrt::SampleComponent::Example allo struct MainPage.

// MainPage.h
...
#include "winrt/SampleComponent.h"

namespace winrt::CppToCSharpWinRT::implementation
{
    struct MainPage : MainPageT<MainPage>
    {
...
        winrt::SampleComponent::Example myExample;
...
    };
}

Nota

In Visual Studio MainPage.h è elencato in MainPage.xaml.

Modificare MainPage.cpp

In MainPage.cppmodificare l'implementazione Mainpage::ClickHandler per chiamare il metodo C# GetMyString.

void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    //myButton().Content(box_value(L"Clicked"));

    hstring myString = myExample.GetMyString();

    myButton().Content(box_value(myString));
}

Eseguire il progetto

A questo punto puoi compilare ed eseguire il progetto. Ogni volta che si fa clic sul pulsante, il numero nel pulsante verrà incrementato.

Screenshot di C++/WinRT windows che chiama un componente C#

Suggerimento

In Visual Studio, creare il progetto del componente: In Solution Explorer, aprite il menu di scelta rapida del progetto CppToCSharpWinRT e scegliete Proprietà, quindi sceglieteDebugging in Proprietà di configurazione. Impostare il tipo di debugger su Managed and Native se si desidera eseguire il debug del codice C# (managed) e C++ (native). Proprietà di debug C++

Versione minima dell'applicazione

Il application minimum della versione del progetto C# controlla la versione di .NET usata per compilare l'applicazione. Ad esempio, scegliendo Windows 10 Fall Creators Update (10.0; Build 16299) o versioni successive abiliterà il supporto del processore .NET Standard 2.0 e Windows Arm64.

Suggerimento

È consigliabile usare versioni minime dell'applicazione inferiori alla 16299 per evitare una configurazione di compilazione aggiuntiva se non è necessario il supporto di .NET Standard 2.0 o Arm64.

Configurazione per Windows 10 Fall Creators Update (10.0; Build 16299)

Seguire questa procedura per abilitare il supporto di .NET Standard 2.0 o Windows Arm64 nei progetti C# a cui si fa riferimento dal progetto C++/WinRT.

In Visual Studio passare a Esplora soluzioni e aprire il menu di scelta rapida per il progetto CppToCSharpWinRT. Scegli Proprietà e imposta la versione minima dell'app di Windows universale su Windows 10 Fall Creators Update (10.0; Build 16299) (o versione successiva). Eseguire la stessa operazione per il progetto SampleComponent.

In Visual Studio aprire il menu di scelta rapida per il progetto CppToCSharpWinRT e scegliere Scarica progetto per aprire CppToCSharpWinRT.vcxproj nell'editor di testo.

Copia e incolla il seguente XML nel primo PropertyGroup in CPPWinRTCSharpV2.vcxproj.

   <!-- Start Custom .NET Native properties -->
   <DotNetNativeVersion>2.2.12-rel-31116-00</DotNetNativeVersion>
   <DotNetNativeSharedLibrary>2.2.8-rel-31116-00</DotNetNativeSharedLibrary>
   <UWPCoreRuntimeSdkVersion>2.2.14</UWPCoreRuntimeSdkVersion>
   <!--<NugetPath>$(USERPROFILE)\.nuget\packages</NugetPath>-->
   <NugetPath>$(ProgramFiles)\Microsoft SDKs\UWPNuGetPackages</NugetPath>
   <!-- End Custom .NET Native properties -->

I valori per DotNetNativeVersion, DotNetNativeSharedLibrarye UWPCoreRuntimeSdkVersion possono variare a seconda della versione di Visual Studio. Per impostarli sui valori corretti, aprire il %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages ed esaminare la sottodirectory per ogni valore nella tabella seguente. La directory %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.Native.Compiler avrà una sottodirectory contenente una versione installata di .NET native che inizia con 2.2. Nell'esempio seguente, è 2.2.12-rel-31116-00.

MSBuild Variable Directory Esempio
DotNetNativeVersion %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.Native.Compiler 2.2.12-rel-31116-00
DotNetNativeSharedLibrary %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\runtime.win10-x64.microsoft.net.native.sharedlibrary 2.2.8-rel-31116-00
UWPCoreRuntimeSdkVersion %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.UWPCoreRuntimeSdk 2.2.14

Nota

Sono disponibili più architetture supportate per Microsoft.Net.Native.SharedLibrary. Sostituire x64 con l'architettura appropriata. Ad esempio, l'architettura arm64 si trova nella directory %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm64.microsoft.net.native.sharedlibrary.

Successivamente, subito dopo la prima PropertyGroup, aggiungere quanto segue (non modificato).

  <!-- Start Custom .NET Native targets -->
  <!-- Import all of the .NET Native / CoreCLR props at the beginning of the project -->
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\Microsoft.Net.UWPCoreRuntimeSdk.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-x86.Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-x64.Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-arm.Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm64.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-arm64.Microsoft.Net.Native.Compiler.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-x86.Microsoft.Net.Native.SharedLibrary.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-x64.Microsoft.Net.Native.SharedLibrary.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-arm.Microsoft.Net.Native.SharedLibrary.props" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm64.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-arm64.Microsoft.Net.Native.SharedLibrary.props" />
  <!-- End Custom .NET Native targets -->

Alla fine del file di progetto, subito prima del tag di chiusura Project, aggiungete il seguente testo (inalterato).

  <!-- Import all of the .NET Native / CoreCLR targets at the end of the project -->
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk\$(UWPCoreRuntimeSdkVersion)\build\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-x86.Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-x64.Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-arm.Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm64.Microsoft.Net.Native.Compiler\$(DotNetNativeVersion)\build\runtime.win10-arm64.Microsoft.Net.Native.Compiler.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x86.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-x86.Microsoft.Net.Native.SharedLibrary.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-x64.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-x64.Microsoft.Net.Native.SharedLibrary.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-arm.Microsoft.Net.Native.SharedLibrary.targets" />
  <Import Condition="'$(WindowsTargetPlatformMinVersion)' &gt;= '10.0.16299.0'" Project="$(NugetPath)\runtime.win10-arm64.Microsoft.Net.Native.SharedLibrary\$(DotNetNativeSharedLibrary)\build\runtime.win10-arm64.Microsoft.Net.Native.SharedLibrary.targets" />
  <!-- End Custom .NET Native targets -->

Ricarica il file di progetto in Visual Studio. In Visual Studio aprire il menu di scelta rapida per il progetto CppToCSharpWinRT e scegliere Reload Project.

Compilazione per .NET Native

È consigliabile compilare e testare l'applicazione con il componente C# compilato in .NET native. In Visual Studio aprire il menu di scelta rapida per il progetto CppToCSharpWinRT e scegliere Scarica progetto per aprire CppToCSharpWinRT.vcxproj nell'editor di testo.

Impostare quindi la proprietà UseDotNetNativeToolchain su true nelle configurazioni Release e Arm64 nel file di progetto C++.

In Visual Studio aprire il menu di scelta rapida per il progetto CppToCSharpWinRT e scegliere Scarica progetto.

  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
...
    <UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Platform)'=='Arm64'" Label="Configuration">
    <UseDotNetNativeToolchain Condition="'$(UseDotNetNativeToolchain)'==''">true</UseDotNetNativeToolchain>
  </PropertyGroup>

Riferimento ad altri pacchetti nuget C#

Se il componente C# fa riferimento ad altri pacchetti nuget, il file di progetto dell'applicazione potrebbe richiedere dipendenze di file di elenco dal pacchetto nuget come contenuto della distribuzione. Ad esempio, se il componente C# fa riferimento al pacchetto nuget Newtonsoft.Json, è necessario fare riferimento anche allo stesso pacchetto NuGet e alla stessa dipendenza di file nel progetto dell'applicazione.

Nel file SampleComponent.csproj aggiungere il riferimento al pacchetto NuGet:

    <PackageReference Include="Newtonsoft.Json">
      <Version>13.0.1</Version>
    </PackageReference>

Nel progetto CppToCSharpWinRT individuare il file packages.config e aggiungere il riferimento nuget appropriato. Verrà installato il pacchetto nuget nella cartella del pacchetto della soluzione.

In packages.configaggiungere lo stesso riferimento al pacchetto NuGet:

  <package id="Newtonsoft.Json" version="13.0.1" targetFramework="native" developmentDependency="true" />

Aggiungere quindi quanto segue al file di progetto dell'applicazione per fare riferimento alla dipendenza del file appropriata dalla cartella del pacchetto della soluzione. Ad esempio, in CppToCSharpWinRT.vcxproj aggiungere quanto segue:

  <ItemGroup>
    <None Include="..\packages\Newtonsoft.Json.13.0.1\lib\netstandard2.0\Newtonsoft.Json.dll">
      <Link>%(Filename)%(Extension)</Link>
      <DeploymentContent>true</DeploymentContent>
    </None>
  </ItemGroup>