后向兼容性准则
编写后向兼容代码可能很难且难以测试。 本文讨论了在 .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 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈