Menulis komponen C# Windows Runtime untuk digunakan dari aplikasi C++/WinRT

Topik ini memancang Anda melalui proses penambahan komponen C# sederhana ke proyek C++/WinRT Anda.

Visual Studio memudahkan penulisan dan penyebaran jenis Windows Runtime kustom Anda sendiri di dalam proyek komponen Windows Runtime (WRC) yang ditulis dengan C# atau Visual Basic, lalu mereferensikan WRC tersebut dari proyek aplikasi C++, dan untuk mengonsumsi jenis kustom tersebut dari aplikasi tersebut.

Secara internal, jenis Windows Runtime Anda dapat menggunakan fungsionalitas .NET apa pun yang diizinkan dalam aplikasi UWP.

Dari sisi eksternal, anggota tipe Anda hanya dapat mengekspos tipe Windows Runtime sebagai parameter dan nilai kembalian. Saat Anda membangun solusi, Visual Studio membangun proyek WRC .NET Anda, lalu menjalankan langkah build yang membuat file metadata Windows (.winmd). Ini adalah komponen Windows Runtime Anda (WRC), yang Visual Studio sertakan di aplikasi Anda.

Note

.NET secara otomatis memetakan beberapa jenis .NET yang umum digunakan, seperti jenis data primitif dan jenis pengumpulan, ke Windows Runtime yang setara. Jenis .NET ini dapat digunakan dalam antarmuka publik komponen Windows Runtime, dan akan muncul kepada pengguna komponen sebagai jenis Windows Runtime yang sesuai. Lihat komponen Windows Runtime dengan C# dan Visual Basic.

Prasyarat

  • Windows 10
  • Microsoft Visual Studio

Membuat Aplikasi Kosong

Di Visual Studio, buat proyek baru menggunakan templat proyek Aplikasi Kosong (C++/WinRT) (untuk aplikasi desktop WinUI 3, gunakan templat Aplikasi Kosong, Dikemas (WinUI 3 di Desktop). Pastikan Anda menggunakan templat (C++/WinRT), dan bukan templat (Universal Windows).

Atur nama proyek baru ke CppToCSharpWinRT sehingga struktur folder Anda akan cocok dengan panduan.

Menambahkan Komponen Windows Runtime C# ke Solusi

Di Visual Studio, buat komponen project: Di Penjelajah Solusi, buka menu pintasan untuk solusi CppToCSharpWinRT dan pilih Tambahkan, lalu pilih Project Baru untuk menambahkan C# baru project ke solusi. Di bagian Templat terinstal dari kotak dialog Tambahkan Project Baru, pilih Visual C#, lalu pilih Windows, lalu Universal. Pilih templat Komponen Windows Runtime (Universal Windows) dan masukkan SampleComponent untuk nama proyek.

Note

Pada kotak dialog Proyek Platform Windows Universal Baru, pilih Windows 10 Creators Update (10.0; Build 15063) sebagai versi minimum. Silakan lihat bagian Versi Minimum Aplikasi di bawah ini untuk informasi lebih lanjut.

Menambahkan metode C# GetMyString

Dalam proyek SampleComponent , ubah nama kelas dari Class1 menjadi Contoh. Kemudian tambahkan dua anggota sederhana ke kelas , bidang privat int dan metode instans bernama GetMyString:

    public sealed class Example
    {
        int MyNumber;

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

Note

Secara default, kelas ditandai disegel publik. Semua kelas Windows Runtime yang Anda ekspos dari komponen Anda harus disegel.

Note

Opsional: Untuk mengaktifkan IntelliSense untuk anggota yang baru ditambahkan, di Penjelajah Solusi, buka menu pintasan untuk proyek SampleComponent, lalu pilih Build.

Mereferensikan C# SampleComponent dari proyek CppToCSharpWinRT

Di Penjelajah Solusi, di proyek C++/WinRT, buka menu pintasan untuk Referensi, lalu pilih Tambahkan Referensi untuk membuka dialog Tambahkan Referensi. Pilih Proyek, lalu pilih Solusi. Pilih kotak centang untuk proyek SampleComponent dan pilih OK untuk menambahkan referensi.

Note

Opsional: Untuk mengaktifkan IntelliSense untuk proyek C++/WinRT, di Penjelajah Solusi, buka menu pintasan untuk proyek CppToCSharpWinRT, lalu pilih Bangun.

Edit MainPage.h

Buka MainPage.h di proyek CppToCSharpWinRT lalu tambahkan dua item. Pertama tambahkan #include "winrt/SampleComponent.h" di akhir #include pernyataan, lalu winrt::SampleComponent::Example bidang ke MainPage struct.

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

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

Note

Dalam Visual Studio, MainPage.h tercantum di bawah MainPage.xaml.

Edit MainPage.cpp

Di MainPage.cpp, ubah implementasi Mainpage::ClickHandler untuk memanggil metode C# GetMyString.

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

    hstring myString = myExample.GetMyString();

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

Jalankan proyek

Anda sekarang dapat membangun dan menjalankan proyek. Setiap kali Anda mengklik tombol, angka di tombol akan bertahap.

Cuplikan layar Windows C++/WinRT yang memanggil komponen C#

Tip

Di Visual Studio, buat proyek komponen: Di Penjelajah Solusi, buka menu pintasan untuk proyek CppToCSharpWinRT dan pilih Properti, lalu pilih Debugging di bawah Properti Konfigurasi. Atur Jenis Debugger ke Terkelola dan Asli jika Anda ingin men-debug kode C# (terkelola) dan C++ (asli). Properti Penelusuran Kesalahan C++

Versi Minimum Aplikasi

Minimum Aplikasi dari versi proyek C# akan mengontrol versi .NET yang digunakan untuk mengkompilasi aplikasi. Misalnya, memilih Windows 10 Fall Creators Update (10.0; Build 16299) atau yang lebih baru akan mengaktifkan dukungan prosesor .NET Standard 2.0 dan Windows Arm64.

Tip

Sebaiknya gunakan versi Minimum Aplikasi yang lebih rendah dari 16299 untuk menghindari konfigurasi build tambahan jika dukungan .NET Standard 2.0 atau Arm64 tidak diperlukan.

Konfigurasikan untuk pembaruan Windows 10 Fall Creators (10.0; Build 16299)

Ikuti langkah-langkah ini untuk mengaktifkan dukungan .NET Standard 2.0 atau Windows Arm64 dalam proyek C# yang dirujuk dari proyek C++/WinRT Anda.

Di Visual Studio, buka Penjelajah Solusi dan buka menu pintasan untuk proyek CppToCSharpWinRT. Pilih Properti dan atur versi Universal Windows App Min ke Windows 10 Fall Creators Update (10.0; Build 16299) (atau lebih tinggi). Lakukan hal yang sama untuk proyek SampleComponent .

Di Visual Studio, buka menu pintasan untuk proyek CppToCSharpWinRT dan pilih Lepaskan Proyek untuk membuka CppToCSharpWinRT.vcxproj di editor teks.

Salin dan tempel XML berikut ke xml pertama PropertyGroup di 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 -->

Nilai untuk DotNetNativeVersion, DotNetNativeSharedLibrary, dan UWPCoreRuntimeSdkVersion dapat bervariasi tergantung pada versi Visual Studio. Untuk mengaturnya ke nilai yang %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages benar, buka dan lihat sub-direktori untuk setiap nilai dalam tabel di bawah ini. Direktori %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.Native.Compiler akan memiliki sub-direktori yang berisi versi .NET asli yang diinstal yang dimulai dengan 2.2. Dalam contoh di bawah ini, itu adalah 2.2.12-rel-31116-00.

Variabel MSBuild Direktori Contoh
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

Note

Ada beberapa arsitektur yang didukung untuk Microsoft. Net.Native.SharedLibrary. Ganti x64 dengan arsitektur yang sesuai. Misalnya, arsitektur arm64 akan ada di direktori %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm64.microsoft.net.native.sharedlibrary.

Selanjutnya, segera setelah yang pertama PropertyGroup, tambahkan yang berikut ini (tidak diubah).

  <!-- 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 -->

Di akhir file project, tepat sebelum tag penutupProject, tambahkan yang berikut ini (tidak diubah).

  <!-- 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 -->

Muat ulang file proyek di Visual Studio. Untuk melakukan ini, di Visual Studio Penjelajah Solusi, buka menu pintasan untuk project CppToCSharpWinRT dan pilih Muat Ulang Project.

Membangun untuk .NET Native

Disarankan untuk membangun dan menguji aplikasi Anda dengan komponen C# yang dibangun terhadap .NET asli. Di Visual Studio, buka menu pintasan untuk proyek CppToCSharpWinRT dan pilih Lepaskan Proyek untuk membuka CppToCSharpWinRT.vcxproj di editor teks.

Selanjutnya, atur UseDotNetNativeToolchain properti ke true dalam konfigurasi Rilis dan Arm64 dalam file proyek C++.

Di Visual Studio Penjelajah Solusi, buka menu pintasan untuk project CppToCSharpWinRT dan pilih Muat Ulang Project.

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

Merujuk ke paket NuGet C# lainnya

Jika komponen C# mereferensikan paket nuget lainnya, file proyek aplikasi mungkin memerlukan dependensi file daftar dari paket nuget sebagai konten penyebaran. Misalnya, jika komponen C# mereferensikan paket nuget Newtonsoft.Json, paket nuget dan dependensi file yang sama juga harus dirujuk dalam proyek aplikasi.

Dalam file SampleComponent.csproj , tambahkan referensi paket nuget:

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

Dalam proyek CppToCSharpWinRT , temukan file packages.config dan tambahkan referensi nuget yang sesuai. Ini akan menginstal paket nuget ke dalam folder paket solusi.

Di packages.config, tambahkan referensi paket nuget yang sama:

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

Kemudian tambahkan yang berikut ini ke file proyek aplikasi untuk mereferensikan dependensi file yang sesuai dari folder paket solusi. Misalnya, di CppToCSharpWinRT.vcxproj tambahkan yang berikut ini:

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