@@ -379,77 +379,53 @@ protected virtual IEnumerable<MemberInfo> GetTypeMembers(Type type)
379379 /// </summary>
380380 protected virtual CreateObject GetTypeCtor ( EntityMapper mapper )
381381 {
382- var ctors = mapper . ForType . GetConstructors ( ) ;
383-
384- var ctor =
385- ctors . FirstOrDefault ( x => x . GetCustomAttribute < BsonCtorAttribute > ( ) != null && x . GetParameters ( ) . All ( p => Reflection . ConvertType . ContainsKey ( p . ParameterType ) || _basicTypes . Contains ( p . ParameterType ) || p . ParameterType . GetTypeInfo ( ) . IsEnum ) ) ??
386- ctors . FirstOrDefault ( x => x . GetParameters ( ) . Length == 0 ) ??
387- ctors . FirstOrDefault ( x => x . GetParameters ( ) . All ( p => Reflection . ConvertType . ContainsKey ( p . ParameterType ) || _customDeserializer . ContainsKey ( p . ParameterType ) || _basicTypes . Contains ( p . ParameterType ) || p . ParameterType . GetTypeInfo ( ) . IsEnum ) ) ;
388-
389- if ( ctor == null ) return null ;
390-
391- var pars = new List < Expression > ( ) ;
392- var pDoc = Expression . Parameter ( typeof ( BsonDocument ) , "_doc" ) ;
393-
394- // otherwise, need access ctor with parameter
395- foreach ( var p in ctor . GetParameters ( ) )
382+ Type type = mapper . ForType ;
383+ List < CreateObject > Mappings = new List < CreateObject > ( ) ;
384+ bool returnZeroParamNull = false ;
385+ foreach ( ConstructorInfo ctor in type . GetConstructors ( ) )
396386 {
397- // try first get converted named (useful for Id => _id)
398- var name = mapper . Members . FirstOrDefault ( x => x . MemberName . Equals ( p . Name , StringComparison . OrdinalIgnoreCase ) ) ? . FieldName ??
399- p . Name ;
400-
401- var expr = Expression . MakeIndex ( pDoc ,
402- Reflection . DocumentItemProperty ,
403- new [ ] { Expression . Constant ( name ) } ) ;
404-
405- if ( _customDeserializer . TryGetValue ( p . ParameterType , out var func ) )
406- {
407- var deserializer = Expression . Constant ( func ) ;
408- var call = Expression . Invoke ( deserializer , expr ) ;
409- var cast = Expression . Convert ( call , p . ParameterType ) ;
410- pars . Add ( cast ) ;
411- }
412- else if ( _basicTypes . Contains ( p . ParameterType ) )
387+ ParameterInfo [ ] pars = ctor . GetParameters ( ) ;
388+ // For 0 parameters, we can let the Reflection.CreateInstance handle it, unless they've specified a [BsonCtor] attribute on a different constructor.
389+ if ( pars . Length == 0 )
413390 {
414- var typeExpr = Expression . Constant ( p . ParameterType ) ;
415- var rawValue = Expression . Property ( expr , typeof ( BsonValue ) . GetProperty ( "RawValue" ) ) ;
416- var convertTypeFunc = Expression . Call ( typeof ( Convert ) . GetMethod ( "ChangeType" , new Type [ ] { typeof ( object ) , typeof ( Type ) } ) , rawValue , typeExpr ) ;
417- var cast = Expression . Convert ( convertTypeFunc , p . ParameterType ) ;
418- pars . Add ( cast ) ;
391+ returnZeroParamNull = true ;
392+ continue ;
419393 }
420- else if ( p . ParameterType . GetTypeInfo ( ) . IsEnum && this . EnumAsInteger )
394+ KeyValuePair < string , Type > [ ] paramMap = new KeyValuePair < string , Type > [ pars . Length ] ;
395+ int i ;
396+ for ( i = 0 ; i < pars . Length ; i ++ )
421397 {
422- var typeExpr = Expression . Constant ( p . ParameterType ) ;
423- var rawValue = Expression . PropertyOrField ( expr , "AsInt32" ) ;
424- var convertTypeFunc = Expression . Call ( typeof ( Enum ) . GetMethod ( "ToObject" , new Type [ ] { typeof ( Type ) , typeof ( Int32 ) } ) , typeExpr , rawValue ) ;
425- var cast = Expression . Convert ( convertTypeFunc , p . ParameterType ) ;
426- pars . Add ( cast ) ;
398+ ParameterInfo par = pars [ i ] ;
399+ MemberMapper mi = null ;
400+ foreach ( MemberMapper member in mapper . Members )
401+ {
402+ if ( member . MemberName . ToLower ( ) == par . Name . ToLower ( ) && member . DataType == par . ParameterType )
403+ {
404+ mi = member ;
405+ break ;
406+ }
407+ }
408+ if ( mi == null ) { break ; }
409+ paramMap [ i ] = new KeyValuePair < string , Type > ( mi . FieldName , mi . DataType ) ;
427410 }
428- else if ( p . ParameterType . GetTypeInfo ( ) . IsEnum )
411+ if ( i < pars . Length ) { continue ; }
412+ CreateObject toAdd = ( BsonDocument value ) =>
413+ Activator . CreateInstance ( type , paramMap . Select ( x =>
414+ this . Deserialize ( x . Value , value [ x . Key ] ) ) . ToArray ( ) ) ;
415+ if ( ctor . GetCustomAttribute < BsonCtorAttribute > ( ) != null )
429416 {
430- var typeExpr = Expression . Constant ( p . ParameterType ) ;
431- var rawValue = Expression . PropertyOrField ( expr , "AsString" ) ;
432- var convertTypeFunc = Expression . Call ( typeof ( Enum ) . GetMethod ( "Parse" , new Type [ ] { typeof ( Type ) , typeof ( string ) } ) , typeExpr , rawValue ) ;
433- var cast = Expression . Convert ( convertTypeFunc , p . ParameterType ) ;
434- pars . Add ( cast ) ;
417+ return toAdd ;
435418 }
436419 else
437420 {
438- var propInfo = Reflection . ConvertType [ p . ParameterType ] ;
439- var prop = Expression . Property ( expr , propInfo ) ;
440- pars . Add ( prop ) ;
421+ Mappings . Add ( toAdd ) ;
441422 }
442423 }
443-
444- // get `new MyClass([params])` expression
445- var newExpr = Expression . New ( ctor , pars . ToArray ( ) ) ;
446-
447- // get lambda expression
448- var fn = mapper . ForType . GetTypeInfo ( ) . IsClass ?
449- Expression . Lambda < CreateObject > ( newExpr , pDoc ) . Compile ( ) : // Class
450- Expression . Lambda < CreateObject > ( Expression . Convert ( newExpr , typeof ( object ) ) , pDoc ) . Compile ( ) ; // Struct
451-
452- return fn ;
424+ if ( returnZeroParamNull )
425+ {
426+ return null ;
427+ }
428+ return Mappings . FirstOrDefault ( ) ;
453429 }
454430
455431 #endregion
0 commit comments