@@ -197,11 +197,45 @@ private Delegate CreateDeserialize<TResult>(ExecutionContext executionContext)
197197 ilGen . Call ( DataType . Method . IsDBNull ) ;
198198 ilGen . IfTrueS ( isDbNullLabel ) ;
199199 }
200+ if ( propertyHolder . IsChain )
201+ {
202+ ilGen . LoadLocalVar ( 0 ) ;
203+
204+ foreach ( var prop in propertyHolder . PropertyChain . Take ( propertyHolder . PropertyChain . Count - 1 ) )
205+ {
206+ var notNullLabel = ilGen . DefineLabel ( ) ;
207+
208+ ilGen . Dup ( ) ;
209+
210+ ilGen . Call ( prop . GetMethod ) ;
211+
212+ ilGen . IfTrueS ( notNullLabel ) ;
213+
214+ ilGen . Dup ( ) ;
215+
216+ ilGen . New ( prop . PropertyType . GetConstructor ( Type . EmptyTypes ) ) ;
217+
218+ ilGen . Call ( prop . SetMethod ) ;
219+
220+ ilGen . MarkLabel ( notNullLabel ) ;
221+
222+ ilGen . Call ( prop . GetMethod ) ;
223+
224+ }
225+
226+ LoadPropertyValue ( ilGen , executionContext , propertyType , columnDescriptor . FieldType , propertyHolder . TypeHandler ) ;
227+
228+ ilGen . Call ( propertyHolder . SetMethod ) ;
229+ }
230+ else
231+ {
232+ ilGen . LoadLocalVar ( 0 ) ;
233+
234+ LoadPropertyValue ( ilGen , executionContext , propertyType , columnDescriptor . FieldType , propertyHolder . TypeHandler ) ;
235+
236+ ilGen . Call ( propertyHolder . SetMethod ) ;
237+ }
200238
201- ilGen . LoadLocalVar ( 0 ) ;
202- LoadPropertyValue ( ilGen , executionContext , propertyType , columnDescriptor . FieldType ,
203- propertyHolder . TypeHandler ) ;
204- ilGen . Call ( propertyHolder . SetMethod ) ;
205239 if ( ignoreDbNull )
206240 {
207241 ilGen . MarkLabel ( isDbNullLabel ) ;
@@ -278,49 +312,76 @@ public static void ThrowDeserializeException(Exception ex, Object result, int co
278312
279313 private static bool ResolveProperty < TResult > ( ResultMap resultMap , Type resultType ,
280314 ColumnDescriptor columnDescriptor
281- , out PropertyHolder propertyHolder )
315+ , out IPropertyHolder propertyHolder )
282316 {
283317 propertyHolder = null ;
284318 if ( resultMap ? . Properties != null )
285319 {
286320 if ( resultMap . Properties . TryGetValue ( columnDescriptor . ColumnName , out var resultProperty ) )
287321 {
288- var property = resultType . GetProperty ( resultProperty . Name ) ??
289- throw new SmartSqlException ( $ "ResultMap:[{ resultMap . Id } ], can not find property:[{ resultProperty . Name } ] in class:[{ resultType . Name } ]") ;
290- propertyHolder = new PropertyHolder
322+ if ( resultProperty . Name . Contains ( '.' ) )
323+ {
324+ propertyHolder = new PropertyChainHolder (
325+ ParsePropertyChain (
326+ resultMapId : resultMap . Id ,
327+ rootType : resultType ,
328+ propertyPath : resultProperty . Name
329+ ) ,
330+ resultProperty . TypeHandler
331+ ) ;
332+ return true ;
333+ }
334+ else
291335 {
292- Property = property ,
293- TypeHandler = resultProperty . TypeHandler
294- } ;
295- return true ;
336+ var property = resultType . GetProperty ( resultProperty . Name )
337+ ?? throw new SmartSqlException (
338+ $ "ResultMap:[{ resultMap . Id } ], can not find property:[{ resultProperty . Name } ] in class:[{ resultType . Name } ]"
339+ ) ;
340+
341+ propertyHolder = new PropertyHolder ( property , resultProperty . TypeHandler ) ;
342+ return true ;
343+ }
296344 }
297345 }
298346
299347 if ( EntityMetaDataCache < TResult > . TryGetColumnByColumnName ( columnDescriptor . ColumnName ,
300348 out var columnAttribute ) )
301349 {
302- propertyHolder = new PropertyHolder
303- {
304- Property = columnAttribute . Property ,
305- TypeHandler = columnAttribute . TypeHandler
306- } ;
350+ propertyHolder = new PropertyHolder ( columnAttribute . Property , columnAttribute . TypeHandler ) ;
307351 return true ;
308352 }
309353
310354 if ( EntityMetaDataCache < TResult > . TryGetColumnByPropertyName ( columnDescriptor . PropertyName ,
311355 out columnAttribute ) )
312356 {
313- propertyHolder = new PropertyHolder
314- {
315- Property = columnAttribute . Property ,
316- TypeHandler = columnAttribute . TypeHandler
317- } ;
357+ propertyHolder = new PropertyHolder ( columnAttribute . Property , columnAttribute . TypeHandler ) ;
318358 return true ;
319359 }
320360
321361 return false ;
322362 }
323363
364+ private static List < PropertyInfo > ParsePropertyChain ( string resultMapId , Type rootType , string propertyPath )
365+ {
366+ var propertyNames = propertyPath . Split ( '.' ) ;
367+ var chain = new List < PropertyInfo > ( ) ;
368+ Type currentType = rootType ;
369+
370+ foreach ( var name in propertyNames )
371+ {
372+ var property = currentType . GetProperty ( name ) ;
373+ if ( property == null )
374+ {
375+ throw new SmartSqlException ( $ "ResultMap:[{ resultMapId } ], Cannot find property:[{ name } ] in type:[{ currentType . Name } ] for path:[{ propertyPath } ]") ;
376+ }
377+
378+ chain . Add ( property ) ;
379+ currentType = property . PropertyType ;
380+ }
381+
382+ return chain ;
383+ }
384+
324385 private void LoadPropertyValue ( ILGenerator ilGen , ExecutionContext executionContext ,
325386 Type propertyType , Type fieldType , String typeHandler )
326387 {
0 commit comments