ET版本:7.0
Unity版本:2021.3.21
Net版本:
问题背景:场景是这样的,就是一个对象,使用ToBson打成二进制传递给客户端,但想屏蔽其中的字段,如果使用[BsonIgnore]来标记字段,那么存贮数据库的时候也会忽略字段。我想数据库存贮时不影响,只在调用ToBson来序列化发送给客户端时屏蔽。
尝试过的方案
1、自定义序列化接口IBsonSerializer<T> 自定义 一个属性 BsonSerializerIgnoreAttribute
在序列化时候反射出自己定义的属性进行忽略,如下
在ToBson时传入接口,但问题是如果对象有嵌套,比如如下数据结构,那么嵌套类型中屏蔽字段就会失效
如果使用 BsonSerializer.RegisterSerializer 来全局注册自定义序列化类,确实可以实现嵌套失效的问题,但全局注册就和[BsonIgnore]一样了,会在数据库中也屏蔽到对应字段,没必要自己实现。而且 BsonSerializer.RegisterSerializer 方法只有注册,没有注销。
2、封装ToBson方法,在序列化给客户端数据前,用反射把对象内的字段设置为默认值,再使用[BsonIgnoreIfDefault]特性,这样会忽略掉默认值实现屏蔽字段。但这个方案问题是,反射改变了对象的内字段的引用,序列化后这个对象里面原本的值就会消失。除非Clone一个对象用来序列化,但不论是利用反射或者实现接口来实现Clone,成本都过高。
Pass的方案
1、用[JsonIgnore]给客户端发送消息用Json序列化不用Bson,方案可行,但不采纳。Json数据量太大,屏蔽字段后的Json,比不屏蔽字段的Bson数据量还要大,不符合需求。
2、不用ToBson来穿二进制数据,直接在Proto里定义数据。方案可行,但不采纳。ToBson序列化数据灵活,而且Proto中定义对于嵌套多的复杂数据不友好。
方向
个人觉得自定义序列化的方案一是可行的,但问题出在无法解决嵌套问题。关键点在使用
bsonWriter.WriteName(field.Name);
BsonSerializer.Serialize(bsonWriter, field.PropertyType, propertyValue);
这两个方法来写入Bson数据时如何处理嵌套?希望有对Bson相关接口熟悉的大佬前来回答。
GameEnginer1
1.pb-net可以光使用标签,跳过不用proto文件生成class,C#内置的复杂结构也能用,用【protoignore】标注不想下发的字段
2。mgo里直接存pb的class,2种标签可以给同一个变量用
3.发送pb的二进制给客户端
你这样使用问题比较大,比如字典中有些kv要传给客户端,有些不想传给客户端就做不了,比如数值组件,还有某些buff等等。所以这个方案ET并没有使用
egametang 意思是这样的嵌套数据结构本身就不合理
List很合理,只是你这样序列化不合理
别悬赏了。给又不给。真要悬赏就去群里了。
Long 你给方案我给钱啊,你的方案呢?
Long 你是有解决方案,怕我不给钱?还是没解决方案,纯粹来口嗨?
GameEnginer1 E大不是给了,有什么用
Long 你看题目了吗?E大给的不是解决方案,没实现我的需求。您要是有本事,上手说点干活。别整天水。
Long 或者来和我辩论辩论问题,搁这里装啥呢?群里我是不知道怎么悬赏,群公告说有事先去论坛,我就来论坛本来是发帖讨论的,看到有悬赏的标签,寻思100块钱而已。没想到钓出个你。
Long E大给了,您看了吗?你来解释解释我这样序列化的不合理之处在哪里?你真懂了吗?既然不合理,那如何做合理?出来解释一下?
论坛提问不用悬赏
疯gou乱咬人,可怕