@@ -30,7 +30,12 @@ public partial class BsonMapper
3030 /// Mapping cache between Class/BsonDocument
3131 /// </summary>
3232 private readonly Dictionary < Type , EntityMapper > _entities = new Dictionary < Type , EntityMapper > ( ) ;
33-
33+
34+ /// <summary>
35+ /// Unfinished mapping cache between Class/BsonDocument
36+ /// </summary>
37+ private readonly Dictionary < Type , EntityMapper > _buildEntities = new Dictionary < Type , EntityMapper > ( ) ;
38+
3439 /// <summary>
3540 /// Map serializer/deserialize for custom types
3641 /// </summary>
@@ -227,6 +232,8 @@ public BsonMapper UseLowerCaseDelimiter(char delimiter = '_')
227232 #endregion
228233
229234 #region GetEntityMapper
235+
236+
230237
231238 /// <summary>
232239 /// Get property mapper between typed .NET class and BsonDocument - Cache results
@@ -235,13 +242,30 @@ internal EntityMapper GetEntityMapper(Type type)
235242 {
236243 //TODO: needs check if Type if BsonDocument? Returns empty EntityMapper?
237244
238- if ( ! _entities . TryGetValue ( type , out EntityMapper mapper ) )
245+ if ( _entities . TryGetValue ( type , out EntityMapper mapper ) )
246+ {
247+ return mapper ;
248+ }
249+
250+ lock ( _entities )
239251 {
240- lock ( _entities )
252+ if ( _entities . TryGetValue ( type , out mapper ) )
241253 {
242- if ( ! _entities . TryGetValue ( type , out mapper ) )
243- return this . BuildAddEntityMapper ( type ) ;
254+ return mapper ;
244255 }
256+
257+ if ( _buildEntities . TryGetValue ( type , out EntityMapper buildMapper ) )
258+ {
259+ return buildMapper ;
260+ }
261+
262+ var newMapper = new EntityMapper ( type ) ;
263+ _buildEntities [ type ] = newMapper ;
264+ this . BuildEntityMapper ( newMapper ) ;
265+ _entities [ type ] = newMapper ;
266+
267+ _buildEntities . Remove ( type ) ;
268+ return newMapper ;
245269 }
246270
247271 return mapper ;
@@ -251,17 +275,17 @@ internal EntityMapper GetEntityMapper(Type type)
251275 /// Use this method to override how your class can be, by default, mapped from entity to Bson document.
252276 /// Returns an EntityMapper from each requested Type
253277 /// </summary>
254- protected virtual EntityMapper BuildAddEntityMapper ( Type type )
278+ protected void BuildEntityMapper ( EntityMapper mapper )
255279 {
256- var mapper = new EntityMapper ( type ) ;
257- _entities [ type ] = mapper ; //direct add into entities, to solove the DBRef [ GetEntityMapper > BuildAddEntityMapper > RegisterDbRef > RegisterDbRefItem > GetEntityMapper ] Loop call recursion,we stoped at here and GetEntityMapper's _entities.TryGetValue
280+ // var mapper = new EntityMapper(type);
281+ // _entities[type] = mapper;//direct add into entities, to solove the DBRef [ GetEntityMapper > BuildAddEntityMapper > RegisterDbRef > RegisterDbRefItem > GetEntityMapper ] Loop call recursion,we stoped at here and GetEntityMapper's _entities.TryGetValue
258282
259283 var idAttr = typeof ( BsonIdAttribute ) ;
260284 var ignoreAttr = typeof ( BsonIgnoreAttribute ) ;
261285 var fieldAttr = typeof ( BsonFieldAttribute ) ;
262286 var dbrefAttr = typeof ( BsonRefAttribute ) ;
263287
264- var members = this . GetTypeMembers ( type ) ;
288+ var members = this . GetTypeMembers ( mapper . ForType ) ;
265289 var id = this . GetIdMember ( members ) ;
266290
267291 foreach ( var memberInfo in members )
@@ -288,8 +312,8 @@ protected virtual EntityMapper BuildAddEntityMapper(Type type)
288312 }
289313
290314 // create getter/setter function
291- var getter = Reflection . CreateGenericGetter ( type , memberInfo ) ;
292- var setter = Reflection . CreateGenericSetter ( type , memberInfo ) ;
315+ var getter = Reflection . CreateGenericGetter ( mapper . ForType , memberInfo ) ;
316+ var setter = Reflection . CreateGenericSetter ( mapper . ForType , memberInfo ) ;
293317
294318 // check if property has [BsonId] to get with was setted AutoId = true
295319 var autoId = ( BsonIdAttribute ) CustomAttributeExtensions . GetCustomAttributes ( memberInfo , idAttr , true ) . FirstOrDefault ( ) ;
@@ -324,7 +348,7 @@ protected virtual EntityMapper BuildAddEntityMapper(Type type)
324348 }
325349
326350 // support callback to user modify member mapper
327- this . ResolveMember ? . Invoke ( type , memberInfo , member ) ;
351+ this . ResolveMember ? . Invoke ( mapper . ForType , memberInfo , member ) ;
328352
329353 // test if has name and there is no duplicate field
330354 // when member is not ignore
@@ -333,8 +357,6 @@ protected virtual EntityMapper BuildAddEntityMapper(Type type)
333357 mapper . Members . Add ( member ) ;
334358 }
335359 }
336-
337- return mapper ;
338360 }
339361
340362 /// <summary>
0 commit comments