Orleans 程式碼產生

在 Orleans 7.0 之前,來源產生更為手動,而且需要明確的開發人員介入。 從 Orleans 7.0 開始,程式碼產生是自動的,不需要開發人員介入。 不過,在某些情況下,開發人員可能會想要影響程式碼產生,例如,為非自動產生的類型產生程式碼,或為另一個元件中的類型產生程式碼。

啟用程式碼產生

Orleans 會在建置時期為您的應用程式產生 C# 原始程式碼。 所有專案,包括您的主機,都必須安裝適當的 NuGet 套件,才能啟用程式碼產生。 下列為可用的套件:

使用 GenerateSerializerAttribute 來指定型別是要串行化,而且應該為型別產生串行化程式碼。 如需詳細資訊,請參閱 使用 Orleans 序列化

Orleans 執行階段會使用產生的程式碼,以確保在整個叢集內使用的型別能夠正確序列化,以及產生常用樣板,以擷取方法傳送、例外狀況傳播和其他內部執行階段概念的實作詳細資料。 您可以在專案建置期間或應用程式初始化時執行程式碼產生。

建置期間會發生什麼情況?

在建置時期,Orleans 會針對標示為 GenerateSerializerAttribute 的所有型別產生程式碼。 如果型別未標示為 GenerateSerializer,則不會由 Orleans 串行化。

如果您要使用 F# 或 Visual Basic 進行開發,您也可以使用程式碼產生。 如需詳細資訊,請參閱下列範例:

這些範例示範如何取用 Orleans.GenerateCodeForDeclaringAssemblyAttribute,指定來源產生器應該檢查和產生來源之元件中的型別。

在建置時期執行程式碼產生是慣用方法。 建置時期程式碼產生可使用下列其中一個套件來啟用:

  • Microsoft.Orleans.OrleansCodeGenerator.Build。 此套件使用 Roslyn 進行程式碼產生,並使用 .NET 反映進行分析。
  • Microsoft.Orleans.CodeGenerator.MSBuild。 新的程式碼產生套件,進行程式碼產生和程式碼分析時均使用 Roslyn。 此套件不會載入應用程式二進位檔,因此可避免因相依性版本衝突和目標架構不同而造成的問題。 新的程式碼產生器也改善了對累加建置的支援,而應該可縮短建置時間。

其中一個套件應安裝到所有包含粒紋、粒紋介面、自訂序列化程式,或在粒紋之間傳送的型別的專案中。 安裝套件時,會將目標插入專案中,進而在建置時期產生程式碼。

套件 (Microsoft.Orleans.CodeGenerator.MSBuildMicrosoft.Orleans.OrleansCodeGenerator.Build) 都僅支援 C# 專案。 若要支援其他語言,須使用後續說明的 Microsoft.Orleans.OrleansCodeGenerator 套件,或建立 C# 專案作為目標,用於使用其他語言撰寫的組件所產生的程式碼。

您可以藉由在目標專案的 .csproj 檔案中指定 OrleansCodeGenLogLevel 的值,在建置時期發出其他診斷。 例如: <OrleansCodeGenLogLevel>Trace</OrleansCodeGenLogLevel>

初始化期間會發生什麼情況?

在 Orleans 7+ 中,初始化期間不會發生任何動作。 程式碼產生是在建置時期執行。

藉由安裝 Microsoft.Orleans.OrleansCodeGenerator 套件和使用 ApplicationPartManagerCodeGenExtensions.WithCodeGeneration 擴充方法,可於初始化期間在用戶端和定址接收器上執行程式碼產生:

builder.ConfigureApplicationParts(
    parts => parts
        .AddApplicationPart(typeof(IRuntimeCodeGenGrain).Assembly)
        .WithCodeGeneration());

在前述範例中,builder 可以是 ISiloHostBuilderIClientBuilder 的執行個體。 選用的 ILoggerFactory 執行個體可傳至 WithCodeGeneration,以在程式碼產生期間啟用記錄,例如:

ILoggerFactory codeGenLoggerFactory = new LoggerFactory();
codeGenLoggerFactory.AddProvider(new ConsoleLoggerProvider());
    builder.ConfigureApplicationParts(
        parts => parts
            .AddApplicationPart(typeof(IRuntimeCodeGenGrain).Assembly)
            .WithCodeGeneration(codeGenLoggerFactory));

影響程式碼產生

GenerateSerializerAttribute 套用至類型時,您也可以套用 IdAttribute 來唯一識別成員。 同樣地,您也可以使用 AliasAttribute 來套用別名。 如需影響程式碼產生的詳細資訊,請參閱 使用 Orleans 串行化

在程式碼產生期間,您可以針對特定型別影響程式碼的產生。 對於粒紋介面、粒紋類別、粒紋狀態,以及在粒紋方法中傳入作為引數的型別,程式碼會自動產生。 如果型別不符合這些準則,可以使用下列方法進一步引導程式碼產生。

SerializableAttribute 新增至型別,會指示程式碼產生器為該型別產生序列化程式。

新增 [assembly: GenerateSerializer(Type)] 至專案,會指示程式碼產生器將該型別視為可序列化,且若無法為該型別產生序列化程式 (例如,因為無法存取該型別),將會導致錯誤。 在程式碼產生啟用的情況下,此錯誤將會中止建置。 此屬性也可讓您從另一個組件產生特定型別的程式碼。

[assembly: KnownType(Type)] 也會指示程式碼產生器包含特定型別 (可能來自參考的組件),但在無法存取型別時不會產生例外狀況。

為所有子型別產生序列化程式

新增 KnownBaseTypeAttribute 至介面或類別,會指示程式碼產生器為所有繼承/實作該型別的型別產生序列化程式碼。

為另一個組件中的所有型別產生程式碼

在某些情況下,產生的程式碼無法在建置時期包含於特定組件中。 例如,這可能包括未參考 Orleans 的共用程式庫、以 C# 以外的語言撰寫的組件,以及開發人員沒有原始程式碼的組件。 在這些情況下,為這類組件產生的程式碼可以放在初始化期間參考的個別組件中。

若要為組件啟用此功能:

  1. 建立 C# 專案。
  2. 套件 Microsoft.Orleans.CodeGenerator.MSBuildMicrosoft.Orleans.OrleansCodeGenerator.Build 套件。
  3. 新增對目標組件的參考。
  4. 在 C# 檔案的最上層新增 [assembly: KnownAssembly("OtherAssembly")]

KnownAssemblyAttribute 會指示程式碼產生器檢查指定的組件,並為其中的型別產生程式碼。 屬性可在專案中多次使用。

產生的組件隨後必須在初始化期間新增至用戶端/定址接收器:

builder.ConfigureApplicationParts(
    parts => parts.AddApplicationPart("CodeGenAssembly"));

在前述範例中,builder 可以是 ISiloHostBuilderIClientBuilder 的執行個體。

KnownAssemblyAttribute 具有選用屬性 TreatTypesAsSerializable,可設定為 true 以指示程式碼產生器將該組件內的所有型別都當作已標示為可序列化。