回溯相容性指導方針
撰寫回溯相容程式碼可能很難且難以測試。 本文討論在 .NET Orleans 中撰寫回溯相容程式碼的指導方針。 本文涵蓋 VersionAttribute 和 ObsoleteAttribute 的使用方式。
永不變更現有方法的簽章
由於 Orleans 序列化程式的運作方式,您絕對不應變更現有方法的簽章。
正確範例如下:
[Version(1)]
public interface IMyGrain : IGrainWithIntegerKey
{
// First method
Task MyMethod(int arg);
}
[Version(2)]
public interface IMyGrain : IGrainWithIntegerKey
{
// Method inherited from V1
Task MyMethod(int arg);
// New method added in V2
Task MyNewMethod(int arg, obj o);
}
這是不正確的:
[Version(1)]
public interface IMyGrain : IGrainWithIntegerKey
{
// First method
Task MyMethod(int arg);
}
[Version(2)]
public interface IMyGrain : IGrainWithIntegerKey
{
// Method inherited from V1
Task MyMethod(int arg, obj o);
}
重要
您不應該在程式碼中進行這項變更,因為這是會導致不良副作用的不良做法範例。 這是當您只重新命名參數名稱時,可能發生的情況範例:假設我們在叢集中部署了下列兩個介面版本:
[Version(1)]
public interface IMyGrain : IGrainWithIntegerKey
{
// return a - b
Task<int> Subtract(int a, int b);
}
[Version(2)]
public interface IMyGrain : IGrainWithIntegerKey
{
// return a - b
Task<int> Subtract(int b, int a);
}
此方法看起來完全相同。 但是,如果使用 V1 呼叫用戶端,且要求是由 V2 啟用處理:
var grain = client.GetGrain<IMyGrain>(0);
var result = await grain.Subtract(5, 4); // Will return "-1" instead of expected "1"
這是因為內部 Orleans 序列化程式的運作方式。
避免變更現有的方法邏輯
這似乎顯而易見,但在變更現有方法的本文時,您應該要非常小心。 除非您正在修正錯誤 (bug),否則若有修改程式碼的需求,您最好直接新增方法。
範例:
// V1
public interface MyGrain : IMyGrain
{
// First method
Task MyMethod(int arg)
{
SomeSubRoutine(arg);
}
}
// V2
public interface MyGrain : IMyGrain
{
// Method inherited from V1
// Do not change the body
Task MyMethod(int arg)
{
SomeSubRoutine(arg);
}
// New method added in V2
Task MyNewMethod(int arg)
{
SomeSubRoutine(arg);
NewRoutineAdded(arg);
}
}
請勿從 Grain 介面中移除方法
除非您確定不再使用這些方法,否則您不應該從 Grain 介面中移除方法。 如果您想要移除方法,這應該會在 2 個步驟中完成:
部署 V2 Grain,並將 V1 方法標示為
Obsolete
[Version(1)] public interface IMyGrain : IGrainWithIntegerKey { // First method Task MyMethod(int arg); }
[Version(2)] public interface IMyGrain : IGrainWithIntegerKey { // Method inherited from V1 [Obsolete] Task MyMethod(int arg); // New method added in V2 Task MyNewMethod(int arg, obj o); }
當您確定沒有任何 V1 呼叫時 (V1 實際上不會再部署在執行中的叢集中),請部署 V3 並移除 V1 方法
[Version(3)] public interface IMyGrain : IGrainWithIntegerKey { // New method added in V2 Task MyNewMethod(int arg, obj o); }
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應