Condividi tramite


Reindirizzamento dei tipi in Common Language Runtime

L'inoltro dei tipi consente di spostare un tipo in un altro assembly senza dover ricompilare le applicazioni che usano l'assembly originale.

Si supponga, ad esempio, che un'applicazione usi la Example classe in un assembly denominato Utility.dll. Gli sviluppatori di Utility.dll potrebbero decidere di effettuare il refactoring dell'assembly e nel processo potrebbero spostare la Example classe in un altro assembly. Se la versione precedente di Utility.dll viene sostituita dalla nuova versione di Utility.dll e dal relativo assembly complementare, l'applicazione che usa la Example classe ha esito negativo perché non riesce a individuare la Example classe nella nuova versione di Utility.dll.

Gli sviluppatori di Utility.dll possono evitare questo problema inoltrando le richieste per la Example classe usando l'attributo TypeForwardedToAttribute . Se l'attributo è stato applicato alla nuova versione di Utility.dll, le richieste per la Example classe vengono inoltrate all'assembly che ora contiene la classe . L'applicazione esistente continua a funzionare normalmente, senza ricompilazione.

Inoltrare un tipo

Esistono quattro passaggi per inoltrare un tipo:

  1. Spostare il codice sorgente per il tipo dall'assembly originale all'assembly di destinazione.

  2. Nell'assembly in cui il tipo era precedentemente situato, aggiungere un TypeForwardedToAttribute per il tipo spostato. Il codice seguente mostra l'attributo per un tipo denominato Example spostato.

     [assembly:TypeForwardedToAttribute(Example::typeid)]
    
     [assembly:TypeForwardedToAttribute(typeof(Example))]
    
  3. Compilare ora l'assembly che contiene il tipo.

  4. Ricompilare l'assembly in cui si trovava il tipo, con un riferimento all'assembly che ora contiene il tipo. Ad esempio, se si compila un file C# dalla riga di comando, usare l'opzione Riferimenti (opzioni del compilatore C#) per specificare l'assembly che contiene il tipo. In C++, usare la direttiva #using nel file di origine per specificare l'assembly che contiene il tipo.

Esempio di inoltro dei tipi C#

Continuando dalla descrizione dell'esempio artificioso sopra, immagina di sviluppare il Utility.dll e hai una classe Example. Utility.csproj è una libreria di classi di base:

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

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

</Project>

La Example classe fornisce alcune proprietà ed esegue l'override Object.ToStringdi :

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}";
}

Ora, immagina che ci sia un progetto che consuma risorse e sia rappresentato nell'assembly Consumer. Questo progetto fa riferimento all'assembly Utility. Ad esempio, crea un'istanza dell'oggetto Example e la scrive nella console nel file Program.cs :

using System;
using Common.Objects;

Example example = new();

Console.WriteLine(example);

Quando l'applicazione di consumo viene eseguita, produrrà lo stato dell'oggetto Example. A questo punto, non esiste alcun inoltro dei tipi perché Il file Consume.csproj fa riferimento a Utility.csproj. Tuttavia, lo sviluppatore dell'assembly utilità decide di rimuovere l'oggetto Example come parte di un refactoring. Questo tipo viene spostato in un common.csproj appena creato.

Rimuovendo questo tipo dall'assembly Utility, gli sviluppatori introducono una modifica incompatibile. Tutti i progetti che consumano completamente verranno interrotti quando verranno aggiornati all'assembly Utility più recente.

Anziché richiedere ai progetti di utilizzo di aggiungere un nuovo riferimento all'assembly Comune , è possibile inoltrare il tipo. Poiché questo tipo è stato rimosso dall'assembly Utility, sarà necessario che Utility.csproj faccia riferimento a Common.csproj:

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

Il progetto C# precedente fa ora riferimento all'assembly Comune appena creato. Può trattarsi di un oggetto PackageReference o di un oggetto ProjectReference. L'assembly Utilità deve fornire le informazioni sul reindirizzamento dei tipi. Per convenzione, le dichiarazioni di inoltro dei tipi vengono in genere incapsulate in un singolo file denominato TypeForwarders, si consideri il seguente file C# TypeForwarders.cs nell'assembly Utility:

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

[assembly:TypeForwardedTo(typeof(Example))]

L'assembly Utility fa riferimento all'assembly Common e inoltra il Example tipo. Se si compila l'assembly Utility con le dichiarazioni di inoltro dei tipi e si rilascia il Utility.dll nella cartella Consuming, l'applicazione Consuming funzionerà senza essere compilata.

Vedere anche