Common Language Runtime 中的類型轉送

型別轉送可讓您將型別移至另一個組件,而無須重新編譯使用原始組件的應用程式。

例如,假設應用程式在名為 Utility.dll 的組件中使用 Example 類別。 Utility.dll 的開發人員可能會決定重構組件,在流程中可能會將 Example 類別移至另一個組件。 如果舊版的 Utility.dll 被新版的 Utility.dll 和其隨附組件取代,使用 Example 類別的應用程式就會失敗,因為其在新版 Utility.dll 中找不到 Example 類別。

Utility.dll 的開發人員可以使用 TypeForwardedToAttribute 屬性轉送 Example 類別要求,避免這個狀況。 如果屬性已套用至新版的 Utility.dllExample 類別的要求就會轉送給現在包含類別的組件。 現有的應用程式會繼續正常運作,而不必重新編譯。

轉送類型

轉送型別有四個步驟︰

  1. 將型別的原始程式碼從原始組件移至目的地組件。

  2. 在使用所尋找類型的組件中,為移動的類型新增 TypeForwardedToAttribute。 下列程式碼示範已移動之名為 Example 的型別的屬性。

     [assembly:TypeForwardedToAttribute(Example::typeid)]
    
     [assembly:TypeForwardedToAttribute(typeof(Example))]
    
  3. 編譯現在包含型別的組件。

  4. 重新編譯型別曾經所在的組件,具有現在包含型別之組件的參考。 例如,如果您正在從命令列編譯 C# 檔案,請使用 References (C# 編譯器選項) 選項來指定包含型別的組件。 在 C++ 中,在來源檔案中使用 #using 指示詞以指定包含型別的組件。

C# 類型轉送範例

從上述的範例描述繼續,假設您正在開發 Utility.dll,而且您有 Example 類別。 Utility.csproj 是基本類別庫:

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

  <PropertyGroup>
    <TargetFramework>net6.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}";
}

現在,假設有取用專案,且其是以「取用者」組件表示。 此取用專案會參考 Utility 組件。 例如,其會具現化 Example 物件,並將其寫入至 Program.cs 檔案中的主控台:

using System;
using Common.Objects;

Example example = new();

Console.WriteLine(example);

當取用的應用程式執行時,其會輸出 Example 物件的狀態。 此時,因為 Consuming.csproj 參考 Utility.csproj,所以沒有類型轉送。 不過,Utility 組件的開發人員決定在重構過程中將 Example 物件移除。 此類型會移至新建立的 Common.csproj

開發人員可從 Utility 組件中移除此類型,藉此引進重大變更。 所有取用專案都會在更新為最新的 Utility 組件時中斷。

您可以轉送類型,而不是要求取用專案將新的參考新增至 Common 組件。 由於此類型已從 Utility 組件中移除,因此您必須讓 Utility.csproj 參考 Common.csproj

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

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

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

</Project>

上述 C# 專案現在會參考新建立的 Common 組件。 這可以是 PackageReferenceProjectReference。 Utility 組件必須提供類型轉送資訊。 根據慣例,類型轉送宣告通常會封裝在名為 TypeForwarders 的單一檔案中,請考慮 Utility 組件中的下列 TypeForwarders.cs C# 檔案:

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

[assembly:TypeForwardedTo(typeof(Example))]

Utility 組件會參考 Common 組件,並轉送 Example 類型。 如果您要使用類型轉送宣告來編譯 Utility 組件,並將 Utility.dll 置放到 Consuming 間隔中,取用的應用程式將可運作,而不會進行編譯。

另請參閱