2.2 Orleans 中的代碼生成

<<返回目錄

代碼生成

Orleans運(yùn)行時(shí)利用生成的代碼以確??缂簩?duì)象類型適當(dāng)?shù)匦蛄谢⑶疑砂逊椒▊鬟f、異常傳播和其他內(nèi)部運(yùn)行時(shí)概念的實(shí)現(xiàn)細(xì)節(jié)抽象掉的輔助代碼。(翻譯:野牛bison)

啟用代碼生成

代碼生成有兩種方式:運(yùn)行時(shí)生成和構(gòu)建時(shí)生成。

構(gòu)建時(shí)生成

構(gòu)建時(shí)生成是Orleans的首選方式,可以使用以下的包進(jìn)行構(gòu)建時(shí)代碼生成:

  • Microsoft.Orleans.OrleansCodeGenerator.Build. 使用.Net 反射分析,并使用 Roslyn 生成代碼.
  • Microsoft.Orleans.CodeGenerator.MSBuild. 一個(gè)新的代碼生成庫(kù),它利用Roslyn進(jìn)行代碼生成和代碼分析。 它不會(huì)加載應(yīng)用程序二進(jìn)制文件,因此可以避免因依賴版本沖突和不同的目標(biāo)框架而導(dǎo)致的問題;并且改進(jìn)了對(duì)增量構(gòu)建的支持,可以縮短構(gòu)建時(shí)間。

這些包應(yīng)安裝到所有項(xiàng)目中,包括 Grain, IGrain, 自定義序列化器和在 Grain 間傳遞的類型庫(kù)。安裝包會(huì)將一個(gè) Target 注入到項(xiàng)目中,在構(gòu)建時(shí)將生成代碼。

在 dotnet core中, target配置在xxx.csproj.nuget.g.targets中,例如:

    <Import Project="$(NuGetPackageRoot)microsoft.orleans.codegenerator.msbuild\2.3.2\build\Microsoft.Orleans.CodeGenerator.MSBuild.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.orleans.codegenerator.msbuild\2.3.2\build\Microsoft.Orleans.CodeGenerator.MSBuild.targets')" />

注意:以上兩個(gè)軟件包只支持C#項(xiàng)目, 可以使用下面Microsoft.Orleans.OrleansCodeGenerator包支持其他語(yǔ)言,或者通過(guò)創(chuàng)建C#項(xiàng)目來(lái)支持其他語(yǔ)言,該項(xiàng)目可以充當(dāng)從用其他語(yǔ)言編寫的程序集生成的代碼的目標(biāo)。

通過(guò)在目標(biāo)項(xiàng)目的csproj文件中指定OrleansCodeGenLogLevel的值,可以在構(gòu)建時(shí)收集額外的診斷信息。 例如,

<OrleansCodeGenLogLevel>Trace</OrleansCodeGenLogLevel>。

運(yùn)行時(shí)生成

通過(guò)安裝Microsoft.Orleans.OrleansCodeGenerator包并使用IApplicationPartManager.WithCodeGeneration擴(kuò)展方法,可以在Client 和 Silo 啟動(dòng)時(shí)執(zhí)行代碼生成。

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

在上面的示例中,builder可以是ISiloHostBuilderIClientBuilder的實(shí)例。 ILoggerFactory(可選)實(shí)例可以傳遞給WithCodeGeneration以在代碼生成期間啟用日志記錄,例如:

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

定制代碼生成

為特定類型生成代碼

代碼生成組件會(huì)自動(dòng)為 Grain的接口及其實(shí)現(xiàn)、Grain State和Grain方法的參數(shù)類型自動(dòng)生成代碼。如果要為額外的類型生成代碼,可以用下面的方法來(lái)使組件生成器為它們生成代碼:

  • [Serializable]添加到類型會(huì)指示代碼生成器為該類型生成序列化程序。
  • [assembly:GenerateSerializer(Type)]添加到項(xiàng)目會(huì)指示代碼生成器將該類型視為可序列化,如果無(wú)法為該類型生成序列化程序,則會(huì)導(dǎo)致錯(cuò)誤,例如因?yàn)樵擃愋筒豢稍L問。 如果啟用了代碼生成,則此錯(cuò)誤將暫停構(gòu)建。 此屬性還允許從另一個(gè)程序集生成特定類型的代碼。
  • [assembly:KnownType(Type)]還指示代碼生成器包含特定類型(可能來(lái)自引用的程序集),但如果類型不可訪問則不會(huì)導(dǎo)致異常。

為所有子類型生成代碼

[KnownBaseType]添加到接口或類會(huì)指示代碼生成器為繼承/實(shí)現(xiàn)該類型的所有類型生成序列化代碼。

為另一個(gè)程序集中的所有類型生成代碼

在某些情況下,生成的代碼在構(gòu)建時(shí)不能包含在特定的程序集中。 例如,這可以包括不引用Orleans的共享庫(kù),用C#以外的語(yǔ)言編寫的程序集,以及開發(fā)人員沒有源代碼的程序集。 在這些情況下,可以將這些程序集的生成代碼放入一個(gè)在初始化期間引用的單獨(dú)程序集中。

為了做到這一點(diǎn),我們需要按如下步驟操作:

  • 創(chuàng)建一個(gè) C# 項(xiàng)目
  • 安裝Microsoft.Orleans.CodeGenerator.MSBuildMicrosoft.Orleans.OrleansCodeGenerator.Build
  • 將目標(biāo)程序集添加到引用
  • 在C#文件頂部添加[assembly: KnownAssembly("OtherAssembly")]

KnownAssembly屬性指示代碼生成器檢查指定的程序集并為其中的類型生成代碼。 該屬性可以在項(xiàng)目中多次使用。

然后必須在初始化期間將生成的程序集添加到 Client / Silo中:

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

在上面的示例中,builder可以是ISiloHostBuilderIClientBuilder的實(shí)例。

KnownAssemblyAttribute有一個(gè)可選屬性TreatTypesAsSerializable,可以將其設(shè)置為true以指示代碼生成器視該程序集中的所有類型都為可序列化類型。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容