Nebula2探秘08-对象序列化
happykevins文
Nebula2的对象序列化系统的设计思路:
Nebula2的对象序列化操作是完全依赖于脚本服务存在的。其设计思路就是根据一个Nebula对象的属性生成一个能够重新生成该对象的脚本文件,这个脚本文件必须
需要知道该Nebula对象的类型信息(需要RTTI的支持),其反序列化的过程就是将这
个对象New出来,然后通过一系列的setXXX方法将该对象的属性设回到序列化之前的样子,所以只要脚本服务的接口提供了构造这个序列化脚本文件的接口,Nebula就可以完成序列化操作了。
创建可序列化对象:
如果想创建一个可以支持Nebula序列化的类,必须至少要继承自nObject类,因为序列化需要nObject层的RTTI和脚本支持,但是最好是继承自nRoot类,这样就可以轻易的实现深度序列化(通过NOH将所有子节点都序列化)。本例中的nPersistObj由于没有深度序列化的需求,所以只做了继承自nObject的实现。可以参考nPersistObj的实现来理解Nebula序列化的实现方法。
Nebula2的对象复制(Clone):
另外每一个继承自nObject的Nebula2对象都可以实现Clone的功能;其实这个Clone功能和序列化走的是同一流程,只是没生成脚本文件而直接生成了一个新的对象而已。
下面将创建一个支持序列化的Nebula2对象,该对象需要具备以下条件:
1.支持序列化的对象必须是nObject的子类(一般继承自nRoot)
2.重写SaveCmds方法实现序列化操作
3.在序列化操作中首先要调用父类的SaveCmds方法以确保序列化的完整性
4.支持序列化的对象需要为脚本接口提供相应的属性设置指令,以支持反序列化操作
/*
**************************************************************************
*/
/*
Nebula2-Tutorial08
*/
/*
Persistence-Nebula2的对象序列化
*/
/*
author:happykevins
*/
/*
**************************************************************************
*/
#pragma
once
#include
"
kernel/nobject.h
"
///
----------------------------------------------------------------------------
///
+支持序列化的Nebula2对象
class
nPersistObj:
public
nObject
{
public
:
nPersistObj(){}
~
nPersistObj(){}
///
----------------------------------------------------------------------------
///
序列化的接口
///
@note:saveobjecttopersistentstream
///
----------------------------------------------------------------------------
virtual
bool
SaveCmds(nPersistServer
*
ps);
///
----------------------------------------------------------------------------
///
+支持脚本指令
///
///
setint
void
SetI(
int
i)
{
m_i
=
i;
}
///
setfloat
void
SetF(
float
f)
{
m_f
=
f;
}
///
setstring
void
SetS(
const
char
*
str)
{
m_str
=
n_strdup(str);
}
///
///
+支持脚本指令
///
----------------------------------------------------------------------------
///
printlog
void
Print()
{
n_printf(
"
Int:%d Float:%f String:%s
"
,m_i,m_f,m_str);
}
private
:
int
m_i;
float
m_f;
char
*
m_str;
};
///
///
-支持序列化的Nebula2对象
///
----------------------------------------------------------------------------
//
cpp文件
#include
"
npersistobj.h
"
#include
"
kernel/nkernelserver.h
"
#include
"
kernel/npersistserver.h
"
#include
"
../NebulaUtils/nutildefs.h
"
///
声明为支持脚本的Nebula2对象,继承自nObject
nNebulaScriptModule(nPersistObj,npersistobj,
"
nobject
"
);
///
设置类属性的指令,用于反序列化时的脚本调用
static
void
n_seti(
void
*
,nCmd
*
);
static
void
n_setf(
void
*
,nCmd
*
);
static
void
n_sets(
void
*
,nCmd
*
);
///
向Nebula2对象注册脚本指令
void
nNebulaScriptInitCmds(npersistobj)(nClass
*
clazz)
{
clazz
->
BeginCmds();
clazz
->
AddCmd(
"
v_seti_i
"
,
'
SETI
'
,n_seti);
clazz
->
AddCmd(
"
v_setf_f
"
,
'
SETF
'
,n_setf);
clazz
->
AddCmd(
"
v_sets_s
"
,
'
SETS
'
,n_sets);
clazz
->
EndCmds();
}
///
设置类属性的指令
static
void
n_seti(
void
*
self,nCmd
*
cmd)
{
nPersistObj
*
slf
=
(nPersistObj
*
)self;
slf
->
SetI(cmd
->
In()
->
GetI());
}
static
void
n_setf(
void
*
self,nCmd
*
cmd)
{
nPersistObj
*
slf
=
(nPersistObj
*
)self;
slf
->
SetF(cmd
->
In()
->
GetF());
}
static
void
n_sets(
void
*
self,nCmd
*
cmd)
{
nPersistObj
*
slf
=
(nPersistObj
*
)self;
slf
->
SetS(cmd
->
In()
->
GetS());
}
///
序列化的接口
bool
nPersistObj::SaveCmds(nPersistServer
*
ps)
{
if
(nObject::SaveCmds(ps))
{
nCmd
*
cmd;
cmd
=
ps
->
GetCmd(
this
,
'
SETI
'
);
cmd
->
In()
->
SetI(
this
->
m_i);
ps
->
PutCmd(cmd);
cmd
=
ps
->
GetCmd(
this
,
'
SETF
'
);
cmd
->
In()
->
SetF(
this
->
m_f);
ps
->
PutCmd(cmd);
cmd
=
ps
->
GetCmd(
this
,
'
SETS
'
);
cmd
->
In()
->
SetS(
this
->
m_str);
ps
->
PutCmd(cmd);
return
true
;
}
return
false
;
}
下面是控制序列化对象的代码:
///
----------------------------------------------------------------------------
///
+声明使用的Nebula2Package&Module
nNebulaUseModule(ntclserver);
nNebulaUseModule(npersistobj);
///
-声明使用的Nebula2Package&Module
///
----------------------------------------------------------------------------
///
----------------------------------------------------------------------------
///
+Application
int
main(
int
argc,
const
char
**
argv)
{
///
创建KernelServer
nKernelServer
*
ks
=
n_new(nKernelServer);
nNebulaAddModule(ntclserver);
nNebulaAddModule(npersistobj);
///
创建TclServer作为脚本服务器
///
Nebula2的对象持久化操作是通过脚本来实现的
ks
->
New(
"
ntclserver
"
,
"
/sys/servers/script
"
);
///
获得PersistServer(对象持久化服务)
nPersistServer
*
ps
=
(nPersistServer
*
)ks
->
Lookup(
"
/sys/servers/persist
"
);
///
初始化对象
n_printf(
"
*****OriginalObject*****
"
);
nPersistObj
*
obj
=
(nPersistObj
*
)ks
->
New(
"
npersistobj
"
);
obj
->
SetI(
521
);
obj
->
SetF(
3.14159f
);
obj
->
SetS(
"
HelloNebula2!
"
);
obj
->
Print();
///
----------------------------------------------------------------------------
///
+序列化到文件
///
n_printf(
"
*****UnserialedObject*****
"
);
//
指定持久化模式(FOLD)
ps
->
SetSaveMode(nPersistServer::SAVEMODE_FOLD);
//
序列化到nPersistObj.n2文件
obj
->
SaveAs(
"
bin:nPersistObj.n2
"
);
//
释放New的对象
obj
->
Release();
//
从nPersistObj.n2文件反序列化
obj
=
(nPersistObj
*
)ks
->
Load(
"
bin:nPersistObj.n2
"
);
obj
->
Print();
///
///
-序列化到文件
///
----------------------------------------------------------------------------
///
----------------------------------------------------------------------------
///
+对象Clone
///
n_printf(
"
*****ClonedObject*****
"
);
//
指定持久化模式(CLONE)
ps
->
SetSaveMode(nPersistServer::SAVEMODE_CLONE);
//
执行Clone操作
obj
->
Clone();
//
释放原始对象
obj
->
Release();
//
获得Clone的对象
nPersistObj
*
cloned
=
(nPersistObj
*
)ps
->
GetClone();
cloned
->
Print();
///
///
-对象Clone
///
----------------------------------------------------------------------------
///
销毁KernelServer
n_delete(ks);
getchar();
return
0
;
}
///
-Application
///
----------------------------------------------------------------------------