2
2
using MongoDB . Bson . Serialization . Serializers ;
3
3
using MongoDB . Bson ;
4
4
using System ;
5
+ using System . Collections ;
5
6
using System . Collections . Generic ;
6
7
using System . Linq ;
7
- using System . Linq . Expressions ;
8
- using System . Threading . Tasks ;
9
- using WorkflowCore . Models ;
10
8
using Newtonsoft . Json ;
11
9
12
10
namespace WorkflowCore . Persistence . MongoDB . Services
@@ -17,7 +15,7 @@ public class DataObjectSerializer : SerializerBase<object>
17
15
{
18
16
TypeNameHandling = TypeNameHandling . Objects ,
19
17
} ;
20
-
18
+
21
19
public override object Deserialize ( BsonDeserializationContext context , BsonDeserializationArgs args )
22
20
{
23
21
if ( context . Reader . CurrentBsonType == BsonType . String )
@@ -26,18 +24,103 @@ public override object Deserialize(BsonDeserializationContext context, BsonDeser
26
24
return JsonConvert . DeserializeObject ( raw , SerializerSettings ) ;
27
25
}
28
26
29
- return BsonSerializer . Deserialize ( context . Reader , typeof ( object ) ) ;
27
+ var obj = BsonSerializer . Deserialize ( context . Reader , typeof ( object ) ) ;
28
+ return obj ;
30
29
}
31
30
32
31
public override void Serialize ( BsonSerializationContext context , BsonSerializationArgs args , object value )
33
32
{
34
- var str = JsonConvert . SerializeObject ( value , SerializerSettings ) ;
35
- var doc = BsonDocument . Parse ( str ) ;
36
- ConvertMetaFormat ( doc ) ;
33
+ BsonDocument doc ;
34
+ if ( BsonClassMap . IsClassMapRegistered ( value . GetType ( ) ) )
35
+ {
36
+ doc = value . ToBsonDocument ( ) ;
37
+ doc . Remove ( "_t" ) ;
38
+ doc . InsertAt ( 0 , new BsonElement ( "_t" , value . GetType ( ) . AssemblyQualifiedName ) ) ;
39
+ AddTypeInformation ( doc . Elements , value , string . Empty ) ;
40
+ }
41
+ else
42
+ {
43
+ var str = JsonConvert . SerializeObject ( value , SerializerSettings ) ;
44
+ doc = BsonDocument . Parse ( str ) ;
45
+ ConvertMetaFormat ( doc ) ;
46
+ }
37
47
38
48
BsonSerializer . Serialize ( context . Writer , doc ) ;
39
49
}
40
50
51
+ private void AddTypeInformation ( IEnumerable < BsonElement > elements , object value , string xPath )
52
+ {
53
+ foreach ( var element in elements )
54
+ {
55
+ var elementXPath = string . IsNullOrEmpty ( xPath ) ? element . Name : xPath + "." + element . Name ;
56
+ if ( element . Value . IsBsonDocument )
57
+ {
58
+ var doc = element . Value . AsBsonDocument ;
59
+ doc . Remove ( "_t" ) ;
60
+ doc . InsertAt ( 0 , new BsonElement ( "_t" , GetTypeNameFromXPath ( value , elementXPath ) ) ) ;
61
+ AddTypeInformation ( doc . Elements , value , elementXPath ) ;
62
+ }
63
+ if ( element . Value . IsBsonArray )
64
+ {
65
+ AddTypeInformation ( element . Value . AsBsonArray , value , elementXPath ) ;
66
+ }
67
+ }
68
+ }
69
+
70
+ private string GetTypeNameFromXPath ( object root , string xPath )
71
+ {
72
+ var parts = xPath . Split ( '.' ) . ToList ( ) ;
73
+ object value = root ;
74
+ while ( parts . Count > 0 )
75
+ {
76
+ var subPath = parts [ 0 ] ;
77
+ if ( subPath [ 0 ] == '[' )
78
+ {
79
+ var index = Int32 . Parse ( subPath . Trim ( '[' , ']' ) ) ;
80
+ if ( value . GetType ( ) . IsSubclassOf ( typeof ( IList ) ) || value . GetType ( ) . IsArray )
81
+ {
82
+ IList list = ( IList ) value ;
83
+ value = list [ index ] ;
84
+ }
85
+ else
86
+ {
87
+ throw new NotSupportedException ( ) ;
88
+ }
89
+ }
90
+ else
91
+ {
92
+ var propInfo = value . GetType ( ) . GetProperty ( subPath ) ;
93
+ value = propInfo . GetValue ( value ) ;
94
+ }
95
+
96
+ parts . RemoveAt ( 0 ) ;
97
+ }
98
+
99
+ return value . GetType ( ) . AssemblyQualifiedName ;
100
+ }
101
+
102
+ private void AddTypeInformation ( IEnumerable < BsonValue > elements , object value , string xPath )
103
+ {
104
+ //foreach (var element in elements)
105
+ for ( int i = 0 ; i < elements . Count ( ) ; i ++ )
106
+ {
107
+ var element = elements . ElementAt ( i ) ;
108
+ if ( element . IsBsonDocument )
109
+ {
110
+ var doc = element . AsBsonDocument ;
111
+ var elementXPath = xPath + $ ".[{ i } ]";
112
+ doc . Remove ( "_t" ) ;
113
+ doc . InsertAt ( 0 , new BsonElement ( "_t" , GetTypeNameFromXPath ( value , elementXPath ) ) ) ;
114
+ AddTypeInformation ( doc . Elements , value , elementXPath ) ;
115
+ }
116
+
117
+ if ( element . IsBsonArray )
118
+ {
119
+ AddTypeInformation ( element . AsBsonArray , value , xPath ) ;
120
+ }
121
+ }
122
+ }
123
+
41
124
private static void ConvertMetaFormat ( BsonDocument root )
42
125
{
43
126
var stack = new Stack < BsonDocument > ( ) ;
@@ -72,4 +155,4 @@ private static void ConvertMetaFormat(BsonDocument root)
72
155
}
73
156
}
74
157
}
75
- }
158
+ }
0 commit comments