Переадресация типов в общеязыковой среде CLR

Перенаправление типа позволяет переместить тип в другую сборку без повторной компиляции приложений, использующих исходную сборку.

Предположим, например, что приложение использует класс Example в сборке с именем Utility.dll. Разработчики Utility.dll могут принять решение выполнить рефакторинг сборки и в ходе этого процесса могут переместить класс Example в другую сборку. Если старую версию Utility.dll заменить новой версией Utility.dll и ее сопутствующей сборкой, приложение, использующее класс Example, завершится ошибкой, так как не сможет найти класс Example в новой версии Utility.dll.

Разработчики Utility.dll могут избежать этого, перенаправляя запросы к классу Example с помощью атрибута TypeForwardedToAttribute. Если атрибут применен к новой версии Utility.dll, запросы класса Example перенаправляются в сборку, которая теперь содержит этот класс. Существующее приложение продолжает нормально функционировать без перекомпиляции.

Перенаправление типа

Для перенаправления типа следует выполнить следующую процедуру.

  1. Переместите исходный код для типа из исходной сборки в целевую сборку.

  2. В сборке, где раньше находился тип, добавьте TypeForwardedToAttribute для типа, который был перемещен. В следующем коде показан атрибут для типа с именем Example, который был перемещен.

     [assembly:TypeForwardedToAttribute(Example::typeid)]
    
     [assembly:TypeForwardedToAttribute(typeof(Example))]
    
  3. Скомпилируйте сборку, которая теперь содержит тип.

  4. Перекомпилируйте сборку, где раньше находился тип, со ссылкой на сборку, которая теперь содержит тип. Например, если вы компилируете файл C# из командной строки, используйте параметр "Ссылки " (параметры компилятора C#), чтобы указать сборку, содержащую тип. В C++ используйте директиву #using в исходном файле, чтобы указать сборку, содержащую тип.

Пример пересылки типов C#

Продолжая из приведенного выше описания примера, представьте, что вы разрабатываете Utility.dll, и у вас есть Example класс. Utility.csproj — это базовая библиотека классов:

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

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

</Project>

Класс Example предоставляет несколько свойств и переопределяет 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}";
}

Теперь представьте, что есть потребляемый проект, и он представлен в сборке потребителей. Этот потребляемый проект ссылается на сборку служебной программы. Например, он создает экземпляр Example объекта и записывает его в консоль в файле Program.cs :

using System;
using Common.Objects;

Example example = new();

Console.WriteLine(example);

При запуске используемого Example приложения будет выводить состояние объекта. На этом этапе переадресация типов отсутствует, так как в файле Consuming.csproj нет ссылок на utility.csproj. Однако сборка служебной программы разработчика решает удалить Example объект в рамках рефакторинга. Этот тип перемещается в только что созданный Common.csproj.

Удаляя этот тип из сборки служебной программы, разработчики внедряют критическое изменение. Все используемые проекты будут нарушены при обновлении до последней сборки служебной программы.

Вместо необходимости добавлять новую ссылку на общую сборку, вы можете перенаправлять тип. Так как этот тип был удален из сборки служебной программы, вам потребуется ссылаться на Файл Common.csproj:

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

Предыдущий проект C# теперь ссылается на только что созданную общую сборку. Это может быть либо a PackageReference , либо ProjectReference. Сборка служебной программы должна предоставить сведения о переадресации типов. По объявлениям типа соглашения пересылка обычно инкапсулируются в одном файле с именем TypeForwarders, рассмотрите следующий TypeForwarders.cs файл C# в сборке служебной программы :

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

[assembly:TypeForwardedTo(typeof(Example))]

Служебная сборка ссылается на общуюсборку и перенаправит Example тип. Если вы собираетесь скомпилировать сборку служебной программы с объявлениями пересылки типов и удалить Utility.dll в корзину "Потребление ", потребляющее приложение будет работать без компиляции.

См. также