Criação de um componente do Windows Runtime em C# para uso em um aplicativo C++/WinRT

Este tópico orienta você no processo de adicionar um componente simples em C# a um projeto C++/WinRT.

O Visual Studio facilita a criação e implantação dos seus próprios tipos de Windows Runtime personalizados dentro de um projeto de WRC (componente do Windows Runtime) escrito com C# ou Visual Basic, seguida da referenciação desse WRC de um projeto de aplicativo C++ e do consumo desses tipos personalizados por esse aplicativo.

Internamente, seus tipos de Windows Runtime podem usar qualquer funcionalidade .NET que seja permitida em um aplicativo UWP.

Externamente, os membros do seu tipo podem expor somente tipos do Windows Runtime para seus parâmetros e valores retornados. Quando você compila sua solução, o Visual Studio compila seu projeto de Componente do .NET WRC e executa uma etapa de build que cria um arquivo de metadados do Windows (.winmd). Este é o seu WRC (componente do Windows Runtime), que o Visual Studio inclui no aplicativo.

Observação

O .NET mapeia automaticamente alguns tipos do .NET usados mais frequentemente, como tipos de dados primitivos e tipos de coleção, para os equivalentes do Windows Runtime. Esses tipos do .NET podem ser usados na interface pública de um componente do Windows Runtime e serão exibidos para usuários do componente como os tipos de Windows Runtime correspondentes. Confira Componentes do Windows Runtime com C# e Visual Basic.

Pré-requisitos

Crie um Aplicativo em Branco

No Visual Studio, crie um novo projeto usando o modelo Aplicativo em branco (C++/WinRT) . Certifique-se de que você está usando o modelo (C++/WinRT) e não o (Universal do Windows) .

Defina o nome do novo projeto como CppToCSharpWinRT para que a estrutura de pastas corresponda ao passo a passos.

Adicionar um componente do Windows Runtime em C# à solução

No Visual Studio, crie o projeto de componente: no Gerenciador de Soluções, abra o menu de atalho da solução CppToCSharpWinRT, escolha Adicionar e Novo Projeto para adicionar um novo projeto em C# ou Visual Basic à solução. Na seção Modelos Instalados da caixa de diálogo Adicionar Novo Projeto, escolha Visual C# , seguido de Windows e Universal. Escolha o modelo Componente do Windows Runtime (Universal do Windows) e insira SampleComponent para o nome do projeto.

Observação

Na caixa de diálogo Novo Projeto da Plataforma Universal do Windows, escolha Atualização do Windows 10 para Criadores (10.0; Build 15063) como a versão mínima. Confira a seção Versão Mínima do Aplicativo abaixo para obter mais informações.

Adicionar o método GetMyString do C#

No projeto SampleComponent, altere o nome da classe de Class1 para Example. Em seguida, adicione dois membros simples à classe, um campo int privado e um método de instância chamado GetMyString:

    public sealed class Example
    {
        int MyNumber;

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

Observação

Por padrão, a classe é marcada como public sealed. Todas as classes do Windows Runtime que você expõe no componente precisam ser sealed.

Observação

Opcional: para habilitar o IntelliSense para os membros recém-adicionados, no Gerenciador de Soluções, abra o menu de atalho do projeto SampleComponent e escolha Compilar.

Referenciar o C# SampleComponent do projeto CppToCSharpWinRT

No Gerenciador de Soluções, no projeto do C++/WinRT, abra o menu de atalho de Referências e escolha Adicionar Referência para abrir a caixa de diálogo Adicionar Referência. Escolha Projetos e Solução. Marque a caixa de seleção do projeto SampleComponent e escolha OK para adicionar uma referência.

Observação

Opcional: para habilitar o IntelliSense para o projeto C++/WinRT, no Gerenciador de Soluções, abra o menu de atalho do projeto CppToCSharpWinRT e escolha Compilar.

Editar MainPage.h

Abra MainPage.h no projeto CppToCSharpWinRT e, em seguida, adicione dois itens. Primeiro, adicione #include "winrt/SampleComponent.h" ao final das instruções #include e, em seguida, um campo winrt::SampleComponent::Example ao struct MainPage.

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

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

Observação

No Visual Studio, MainPage.h está listado em MainPage.xaml.

Edite MainPage.cpp

Em MainPage.cpp, altere a implementação de Mainpage::ClickHandler para chamar o método GetMyString do C#.

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

    hstring myString = myExample.GetMyString();

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

Executar o projeto

Agora você poderá compilar e executar o projeto. Cada vez que você clicar no botão, haverá um incremento ao número presente nele.

Captura de tela de C++/WinRT Windows chamando um componente C#

Dica

No Visual Studio, crie o projeto de componente: em Gerenciador de Soluções, abra o menu de atalho para o projeto CppToCSharpWinRT e escolha Propriedades, depois escolha Depuração em Propriedades de Configuração. Defina o tipo de depurador como Gerenciado e Nativo se você quiser depurar o código C# (gerenciado) e C++ (nativo). Propriedades de depuração do C++

Versão mínima do aplicativo

O Mínimo do Aplicativo da versão do projeto C# controlará a versão do .NET usada para compilar o aplicativo. Por exemplo, escolher Windows 10 Fall Creators Update (10.0 ─ Build 16299) ou superior permitirá o suporte ao .NET Standard 2.0 e ao processador Arm64 do Windows.

Dica

É recomendável usar as versões mínimas do aplicativo inferiores a 16299 para evitar a configuração de Build extra se o suporte a .NET Standard 2.0 ou ARM64 não é necessário.

Configurar para o Windows 10 Fall Creators Update (10.0; build 16299)

Siga estas etapas para habilitar o suporte ao .NET Standard 2.0 ou ao Windows ARM64 nos projetos C# referenciados do seu projeto C++/WinRT.

No Visual Studio, vá para a Gerenciador de Soluções e abra o menu de atalho para o projeto CppToCSharpWinRT. Escolha Propriedades e defina a versão mínima do aplicativo universal do Windows para a Windows 10 Fall Creators Update (10,0; Build 16299) . Faça o mesmo para o projeto SampleComponent.

No Visual Studio, abra o menu de atalho do projeto CppToCSharpWinRT e escolha Descarregar Projeto para abrir CppToCSharpWinRT.vcxproj no editor de texto.

Copie e cole o XML a seguir no primeiro PropertyGroup em 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 -->

Os valores para DotNetNativeVersion, DotNetNativeSharedLibrary e UWPCoreRuntimeSdkVersion podem variar dependendo da versão do Visual Studio. Para defini-los corretamente, abra o %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages e examine o subdiretório para cada valor na tabela abaixo. O diretório %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\Microsoft.Net.Native.Compiler terá um subdiretório que conterá uma versão instalada do nativo do .NET que começa com 2.2. No exemplo abaixo, ele é 2.2.12-rel-31116-00.

Variável do MSBuild Diretório Exemplo
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

Observação

Há várias arquiteturas com suporte para Microsoft.Net.Native.SharedLibrary. Substitua x64 pela arquitetura apropriada. Por exemplo, a arquitetura arm64 estaria no diretório %ProgramFiles(x86)%\Microsoft SDKs\UWPNuGetPackages\runtime.win10-arm64.microsoft.net.native.sharedlibrary.

Em seguida, imediatamente após a primeira PropertyGroup, adicione o conteúdo a seguir (inalterado).

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

No final do arquivo de projeto, logo antes da marca de fechamento Project, adicione o conteúdo a seguir (inalterado).

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

Recarregue o arquivo de projeto no Visual Studio. Para fazer isso, no Gerenciador de Soluções do Visual Studio, abra o menu de atalho do projeto CppToCSharpWinRT e escolha Recarregar Projeto.

Compilar para .NET Native

É recomendável compilar e testar o aplicativo com o componente C# criado com base no .NET Native. No Visual Studio, abra o menu de atalho do projeto CppToCSharpWinRT e escolha Descarregar Projeto para abrir CppToCSharpWinRT.vcxproj no editor de texto.

Em seguida, defina a propriedade UseDotNetNativeToolchain como true nas configurações de Versão e ARM64 no arquivo de projeto C++.

No Gerenciador de Soluções do Visual Studio, abra o menu de atalho para o projeto CppToCSharpWinRT e escolha Recarregar Projeto.

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

Referenciando outros pacotes nuget de C#

Se o componente C# estiver referenciando outros pacotes nuget, o arquivo de projeto do aplicativo poderá precisar listar dependências de arquivo do pacote nuget como conteúdo de implantação. Por exemplo, se o componente C# referenciar o pacote nuget Newtonsoft.Json, o mesmo pacote nuget e a dependência de arquivo também deverão ser referenciados no projeto de aplicativo.

No arquivo SampleComponent.csproj, adicione a referência de pacote nuget:

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

No projeto CppToCSharpWinRT, localize o arquivo packages.config e adicione a referência do nuget apropriada. Isso instalará o pacote nuget na pasta do pacote da solução.

Em packages.config, adicione a mesma referência de pacote nuget:

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

Em seguida, adicione o código a seguir ao arquivo de projeto do aplicativo para fazer referência à dependência de arquivo apropriada da pasta do pacote da solução. Por exemplo, em CppToCSharpWinRT.vcxproj, adicione o seguinte:

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