在 Apache Geode 事件侦听器中与 pdx 进行转换
Casting to and from pdx in an Apache Geode event listener
在 中,我询问了 Geode.Net 客户端将 Geode PDX 类型转换为对象(域对象)的问题,这次我在将对象转换为 Geode PDX 类型时遇到了问题。似乎一个区域可以同时包含 pdx 序列化对象类型和其他类型的对象和/或内部对象类型。我猜是通过使用字节偏移量。
无论如何,this link 展示了一种检查对象类型并处理它们的方法:
// get checks Object type and handles each appropriately
Object myObject = myRegion.get(myKey);
作为 PDX 实例或域对象类型:
if (myObject instanceof PdxInstance) {
// get returned PdxInstance instead of domain object
PdxInstance myPdxInstance = (PdxInstance)myObject;
然后使用 GetField
对于 PDX 实例,您可以只更新 1 个字段,非常好...
我的问题是域对象:
else if (myObject instanceof DomainClass) {
// code to handle domain object instance
来自事件侦听器时
public void AfterCreate(EntryEvent<TKey, TVal> ev)
我首先尝试将 ev.NewValue
转换为 Pdx 或域对象,并继续获得以下之一:
当区域中的值为 PdxInstance
时,如果没有如上所述的 if (myObject instanceof PdxInstance)
来防止它,则转换 IPdxInstance pdx = (IPdxInstance)ev.NewValue
给出:
System.InvalidCastException: Unable to cast object of type myObject to type
Apache.Geode.Client.IPdxInstance
这是意料之中的。我似乎通过将区域 <key, value>
创建为 <string, Object>
来破坏 myObject 的 PdxSerialisation,即使 myObject 扩展了 PdxSerializable 并将键和值写入该区域正在经历 ToData()
覆盖。
然后直接处理 myObject
例如 myObject = ev.NewValue
或 myObject.Field1 = ((myObject)(ev.NewValue)).Field1
或类似的变体给出:
Cannot implicitly convert type 'TVal' to 'myObject'
Cannot convert type 'TVal' to 'myObject'
当然 ev.NewValue
到 myObject
的事件应该很简单,所以我错过了什么?否则,我必须使用 ev.Key
(它确实会毫无例外地进行转换)通过使用
从缓存中的区域再次明确地 get
值:
IRegion<string, Object> r = cache.GetRegion<string, Object>(region);
return r[key];
所以当对象已经在 TVal
类型 NewValue
中给出时,为什么我不能在那里访问它? :-s
我建议您删除 "read-serialized=true" 并删除 IPdxInstance 的类型检查。在没有 read-serialized=true 的情况下,您仍然可以在您的区域拥有 PDX 对象。您确实希望回调中的反序列化域对象本身而不是 PDX 实例。关闭读取序列化将实现这一点,并在 AfterCreate 方法中返回反序列化的域对象。
注意:以上建议是基于您使用的是 .NET 客户端并且 .NET 给您编译错误这一事实。 Java 客户端不会出现这种情况。有点不解.NET交互为什么要这样做
仅供参考,众所周知,在使用 PDX 的区域中,区域可能包含 PDX 实例或域对象。这是为了性能效率。主节点可以以非 PDX 形式存储域对象以避免序列化成本,但可以在辅助服务器上存储 PDX 版本。这就是为什么客户端在操作实例之前总是需要检查类型。
是的,我知道字符串是您的关键,但我的关键问题是您是否在使用 Native Client。小写 "s" 是一个线索。
每个 programming your application to use PDX instances 区域可以容纳对象或 PDX 包装的对象。对于前者,通过 object
进行转换是可行的。所以我需要写:
object o = ev.NewValue;
if (o.GetType().Name.Equals("PdxInstanceImpl"))
{
PdxInstance myPdx = (PdxInstance)o;
MyObject m = (MyObject)myPdx.GetObject();
string s = m.MyString;
decimal d = m.MyDecimal;
}
else
{
MyObject m = (MyObject)o;
string s = m.MyString;
decimal d = m.MyDecimal;
}
在
无论如何,this link 展示了一种检查对象类型并处理它们的方法:
// get checks Object type and handles each appropriately
Object myObject = myRegion.get(myKey);
作为 PDX 实例或域对象类型:
if (myObject instanceof PdxInstance) {
// get returned PdxInstance instead of domain object
PdxInstance myPdxInstance = (PdxInstance)myObject;
然后使用 GetField
对于 PDX 实例,您可以只更新 1 个字段,非常好...
我的问题是域对象:
else if (myObject instanceof DomainClass) {
// code to handle domain object instance
来自事件侦听器时
public void AfterCreate(EntryEvent<TKey, TVal> ev)
我首先尝试将 ev.NewValue
转换为 Pdx 或域对象,并继续获得以下之一:
当区域中的值为 PdxInstance
时,如果没有如上所述的 if (myObject instanceof PdxInstance)
来防止它,则转换 IPdxInstance pdx = (IPdxInstance)ev.NewValue
给出:
System.InvalidCastException: Unable to cast object of type myObject to type
Apache.Geode.Client.IPdxInstance
这是意料之中的。我似乎通过将区域 <key, value>
创建为 <string, Object>
来破坏 myObject 的 PdxSerialisation,即使 myObject 扩展了 PdxSerializable 并将键和值写入该区域正在经历 ToData()
覆盖。
然后直接处理 myObject
例如 myObject = ev.NewValue
或 myObject.Field1 = ((myObject)(ev.NewValue)).Field1
或类似的变体给出:
Cannot implicitly convert type 'TVal' to 'myObject'
Cannot convert type 'TVal' to 'myObject'
当然 ev.NewValue
到 myObject
的事件应该很简单,所以我错过了什么?否则,我必须使用 ev.Key
(它确实会毫无例外地进行转换)通过使用
get
值:
IRegion<string, Object> r = cache.GetRegion<string, Object>(region);
return r[key];
所以当对象已经在 TVal
类型 NewValue
中给出时,为什么我不能在那里访问它? :-s
我建议您删除 "read-serialized=true" 并删除 IPdxInstance 的类型检查。在没有 read-serialized=true 的情况下,您仍然可以在您的区域拥有 PDX 对象。您确实希望回调中的反序列化域对象本身而不是 PDX 实例。关闭读取序列化将实现这一点,并在 AfterCreate 方法中返回反序列化的域对象。
注意:以上建议是基于您使用的是 .NET 客户端并且 .NET 给您编译错误这一事实。 Java 客户端不会出现这种情况。有点不解.NET交互为什么要这样做
仅供参考,众所周知,在使用 PDX 的区域中,区域可能包含 PDX 实例或域对象。这是为了性能效率。主节点可以以非 PDX 形式存储域对象以避免序列化成本,但可以在辅助服务器上存储 PDX 版本。这就是为什么客户端在操作实例之前总是需要检查类型。
是的,我知道字符串是您的关键,但我的关键问题是您是否在使用 Native Client。小写 "s" 是一个线索。
每个 programming your application to use PDX instances 区域可以容纳对象或 PDX 包装的对象。对于前者,通过 object
进行转换是可行的。所以我需要写:
object o = ev.NewValue;
if (o.GetType().Name.Equals("PdxInstanceImpl"))
{
PdxInstance myPdx = (PdxInstance)o;
MyObject m = (MyObject)myPdx.GetObject();
string s = m.MyString;
decimal d = m.MyDecimal;
}
else
{
MyObject m = (MyObject)o;
string s = m.MyString;
decimal d = m.MyDecimal;
}