我有一个IContainerGrain
包含Node
对象列表的谷物。类型的对象Node
需要能够通过这个grain相互通信:
class Node {
public IContainerGrain Container { get; set; } // This is an object reference (!) to the container grain
private void TriggerExecution() {
var receiverId = 123;
Container.GetNode(receiverId).SendSomeMessage(); // Communicate through container grain
}
}
现在我想保持IContainerGrain
包含节点列表的状态。谷物状态的序列化触发所有包含的序列化Nodes
,然后触发IContainerGrain
. 这不受支持,我得到一个例外。
我的方法
我的非工作方法是将 Node.Container 标记为NonSerializable
并在 Grain 中实现以下内容:
public override Task OnActivateAsync()
{
if (State.ContainedNodes == null)
{
State.ContainedNodes = new List<INode>();
}
foreach (var n in State.ContainedNodes)
{
n.Container = this; // On activation initialize container
}
return base.OnActivateAsync();
}
但是,这并不总是有效,我不断获得 NullReferenceExceptions Node.TriggerExecution()
,因为 Container 属性为空。
问题
能够从这个grain中的一个对象存储一个对grain的对象引用的最佳方法是什么?我可以很容易地使用谷物参考,但这会使
Container.GetNode(...)
操作变慢。我知道如果我使用 1:1 的 grain 映射到Node
,则不会存在此问题,但这对我的应用程序来说开销太大。Orleans 序列化是这样存储引用还是总是执行深拷贝?在序列化和反序列化之后保留完整的引用会很棒。