Compartilhar via


Encaminhamento de tipo no Common Language Runtime

O encaminhamento de tipo permite mover um tipo para outro conjunto sem precisar recompilar aplicativos que usam o conjunto original.

Por exemplo, suponha que um aplicativo use a Example classe em um assembly chamado Utility.dll. Os desenvolvedores de Utility.dll podem decidir refatorar o assembly e, no processo, podem mover a Example classe para outro assembly. Se a versão antiga do Utility.dll for substituída pela nova versão do Utility.dll e seu assembly complementar, o aplicativo que usa a Example classe falhará porque não poderá localizar a Example classe na nova versão do Utility.dll.

Os desenvolvedores de Utility.dll podem evitar isso encaminhando solicitações para a Example classe usando o TypeForwardedToAttribute atributo. Se o atributo tiver sido aplicado à nova versão do Utility.dll, as Example solicitações da classe serão encaminhadas para o assembly que agora contém a classe. O aplicativo existente continua funcionando normalmente, sem recompilação.

Encaminhar um tipo

Há quatro etapas para encaminhar um tipo:

  1. Mova o código-fonte para o tipo do assembly original para o conjunto de destino.

  2. No assembly em que o tipo é usado para ser localizado, adicione um TypeForwardedToAttribute para o tipo que foi movido. O código a seguir mostra o atributo de um tipo chamado Example que foi movido.

     [assembly:TypeForwardedToAttribute(Example::typeid)]
    
     [assembly:TypeForwardedToAttribute(typeof(Example))]
    
  3. Compile o assembly que agora contém o tipo.

  4. Recompile o assembly onde o tipo estava localizado, com uma referência ao assembly que agora contém o tipo. Por exemplo, se você estiver compilando um arquivo C# da linha de comando, use a opção Referências (opções do compilador C#) para especificar o assembly que contém o tipo. No C++, use a diretiva #using no arquivo de origem para especificar o assembly que contém o tipo.

Exemplo de encaminhamento de tipo C#

Continuando com a descrição de exemplo inventada acima, imagine que você está desenvolvendo o Utility.dlle tem uma Example classe. O Utility.csproj é uma biblioteca de classes básica:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsing>true</ImplicitUsing>
  </PropertyGroup>

</Project>

A classe Example fornece algumas propriedades e substituições Object.ToString:

using System;

namespace Common.Objects;

public class Example
{
    public string Message { get; init; } = "Hi friends!";

    public Guid Id { get; init; } = Guid.NewGuid();

    public DateOnly Date { get; init; } = DateOnly.FromDateTime(DateTime.Today);

    public sealed override string ToString() =>
        $"[{Id} - {Date}]: {Message}";
}

Agora, imagine que haja um projeto de consumo e ele seja representado no assembly Consumer. Esse projeto de consumo faz referência ao assembly Utility. Por exemplo, isso instancia o objeto Example e o grava no console em seu arquivo Program.cs:

using System;
using Common.Objects;

Example example = new();

Console.WriteLine(example);

Quando o aplicativo de consumo for executado, ele produzirá o estado do Example objeto. Neste ponto, não há nenhum encaminhamento de tipo, pois Consuming.csproj faz referência a Utility.csproj. No entanto, os desenvolvedores do assembly Utility decidem remover o objeto Example como parte de uma refatoração. Esse tipo é movido para um Common.csproj recém-criado.

Ao remover esse tipo do assembly Utility, os desenvolvedores estão introduzindo uma alteração interruptiva. Todos os projetos de consumo serão interrompidos quando forem atualizados para o assembly Utility mais recente.

Em vez de exigir que os projetos de consumo adicionem uma referência ao assembly Common, você pode encaminhar o tipo. Como esse tipo foi removido do assembly Utility, você precisará fazer com que Utility.csproj faça referência a Common.csproj:

<ItemGroup>
  <ProjectReference Include="..\Common\Common.csproj" />
</ItemGroup>

O projeto C# anterior agora faz referência ao assembly Common recém-criado. Isso pode ser um PackageReference ou um ProjectReference. O assembly Utility precisa fornecer as informações de encaminhamento de tipo. Por convenção, declarações de encaminhamento de tipos geralmente são encapsuladas em um único arquivo chamado TypeForwarders. Considere o seguinte arquivo C# TypeForwarders.cs no assembly Utility:

using System.Runtime.CompilerServices;
using Common.Objects;

[assembly:TypeForwardedTo(typeof(Example))]

O assembly Utility faz referência ao assembly Comum e encaminha o tipo Example. Se você quiser compilar o assembly Utility com as declarações de encaminhamento de tipo e remover Utility.dll para a lixeira Consuming, o aplicativo consumidor funcionará sem ser compilado.

Consulte também