@@ -405,26 +405,11 @@ public static IType Basic(string name)
405
405
/// </remarks>
406
406
public static IType Basic ( string name , IDictionary < string , string > parameters )
407
407
{
408
- string typeName ;
409
-
410
408
// Use the basic name (such as String or String(255)) to get the
411
- // instance of the IType object.
412
- IType returnType ;
413
- if ( typeByTypeOfName . TryGetValue ( name , out returnType ) )
414
- {
415
- if ( _obsoleteMessageByAlias . TryGetValue ( name , out string obsoleteMessage ) )
416
- _log . Warn ( "{0} is obsolete. {1}" , name , obsoleteMessage ) ;
417
-
418
- if ( parameters ? . Count > 0 && returnType is IParameterizedType )
419
- {
420
- // The type is parameterized, must apply the parameters to a new instance of the type.
421
- // Some built-in types have internal default constructor like StringType, so we need to
422
- // allow non-public constructors.
423
- returnType = ( IType ) Activator . CreateInstance ( returnType . GetType ( ) , true ) ;
424
- InjectParameters ( returnType , parameters ) ;
425
- }
409
+ // instance of the IType object.
410
+ var returnType = GetBasicTypeByName ( name , parameters ) ;
411
+ if ( returnType != null )
426
412
return returnType ;
427
- }
428
413
429
414
// if we get to here then the basic type with the length or precision/scale
430
415
// combination doesn't exists - so lets figure out which one we have and
@@ -442,7 +427,7 @@ public static IType Basic(string name, IDictionary<string, string> parameters)
442
427
"TypeClassification.PrecisionScale" , name , "It is not a valid Precision/Scale name" ) ;
443
428
}
444
429
445
- typeName = parsedName [ 0 ] . Trim ( ) ;
430
+ string typeName = parsedName [ 0 ] . Trim ( ) ;
446
431
byte precision = Byte . Parse ( parsedName [ 1 ] . Trim ( ) ) ;
447
432
byte scale = Byte . Parse ( parsedName [ 2 ] . Trim ( ) ) ;
448
433
@@ -459,7 +444,7 @@ public static IType Basic(string name, IDictionary<string, string> parameters)
459
444
"TypeClassification.LengthOrScale" , name , "It is not a valid Length or Scale name" ) ;
460
445
}
461
446
462
- typeName = parsedName [ 0 ] . Trim ( ) ;
447
+ string typeName = parsedName [ 0 ] . Trim ( ) ;
463
448
int length = Int32 . Parse ( parsedName [ 1 ] . Trim ( ) ) ;
464
449
465
450
returnType = BuiltInType ( typeName , length ) ;
@@ -478,6 +463,26 @@ public static IType Basic(string name, IDictionary<string, string> parameters)
478
463
return returnType ;
479
464
}
480
465
466
+ private static IType GetBasicTypeByName ( string name , IDictionary < string , string > parameters )
467
+ {
468
+ if ( typeByTypeOfName . TryGetValue ( name , out var returnType ) )
469
+ {
470
+ if ( _obsoleteMessageByAlias . TryGetValue ( name , out string obsoleteMessage ) )
471
+ _log . Warn ( "{0} is obsolete. {1}" , name , obsoleteMessage ) ;
472
+
473
+ if ( parameters ? . Count > 0 && returnType is IParameterizedType )
474
+ {
475
+ // The type is parameterized, must apply the parameters to a new instance of the type.
476
+ // Some built-in types have internal default constructor like StringType, so we need to
477
+ // allow non-public constructors.
478
+ returnType = ( IType ) Activator . CreateInstance ( returnType . GetType ( ) , true ) ;
479
+ InjectParameters ( returnType , parameters ) ;
480
+ }
481
+ return returnType ;
482
+ }
483
+ return null ;
484
+ }
485
+
481
486
internal static IType BuiltInType ( string typeName , int lengthOrScale )
482
487
{
483
488
GetNullableTypeWithLengthOrScale lengthOrScaleDelegate ;
@@ -522,6 +527,23 @@ public static IType HeuristicType(string typeName)
522
527
return HeuristicType ( typeName , null ) ;
523
528
}
524
529
530
+ /// <summary>
531
+ /// Uses heuristics to deduce a NHibernate type given a string naming the
532
+ /// type.
533
+ /// </summary>
534
+ /// <param name="type"></param>
535
+ /// <returns>An instance of <c>NHibernate.Type.IType</c></returns>
536
+ /// <remarks>
537
+ /// We check to see if it implements IType, ICompositeUserType, IUserType, ILifecycle (Association), or
538
+ /// IPersistentEnum. If none of those are implemented then we will serialize the Type to the
539
+ /// database using NHibernate.Type.SerializableType(typeName)
540
+ /// </remarks>
541
+ public static IType HeuristicType ( System . Type type )
542
+ {
543
+ return GetBasicTypeByName ( type . AssemblyQualifiedName , null )
544
+ ?? GetBySystemType ( type , null , null ) ;
545
+ }
546
+
525
547
/// <summary>
526
548
/// Uses heuristics to deduce a NHibernate type given a string naming the type.
527
549
/// </summary>
@@ -532,7 +554,7 @@ public static IType HeuristicType(string typeName, IDictionary<string, string> p
532
554
{
533
555
return HeuristicType ( typeName , parameters , null ) ;
534
556
}
535
-
557
+
536
558
/// <summary>
537
559
/// Uses heuristics to deduce a NHibernate type given a string naming the type.
538
560
/// </summary>
@@ -546,55 +568,71 @@ public static IType HeuristicType(string typeName, IDictionary<string, string> p
546
568
547
569
if ( type != null )
548
570
return type ;
549
-
571
+
550
572
string [ ] parsedTypeName ;
551
- TypeClassification typeClassification = GetTypeClassification ( typeName ) ;
573
+ var typeClassification = GetTypeClassification ( typeName ) ;
552
574
if ( typeClassification == TypeClassification . LengthOrScale )
575
+ {
553
576
parsedTypeName = typeName . Split ( LengthSplit ) ;
577
+ if ( ! int . TryParse ( parsedTypeName [ 1 ] , out int parsedLength ) )
578
+ {
579
+ throw new MappingException ( $ "Could not parse length value '{ parsedTypeName [ 1 ] } ' as int for type '{ typeName } '") ;
580
+ }
581
+ length = parsedLength ;
582
+ }
554
583
else
555
584
parsedTypeName = typeClassification == TypeClassification . PrecisionScale ? typeName . Split ( PrecisionScaleSplit ) : new [ ] { typeName } ;
556
585
557
-
558
586
System . Type typeClass ;
559
587
try
560
588
{
561
589
typeClass = ReflectHelper . ClassForName ( parsedTypeName [ 0 ] ) ; //typeName);
562
590
}
563
591
catch ( Exception )
564
592
{
565
- typeClass = null ;
593
+ return null ;
566
594
}
567
595
568
- if ( typeClass == null )
569
- return null ;
570
-
596
+ return GetBySystemType ( typeClass , parameters , length ) ;
597
+ }
598
+
599
+ private static IType GetBySystemType ( System . Type typeClass , IDictionary < string , string > parameters , int ? length )
600
+ {
571
601
if ( typeof ( IType ) . IsAssignableFrom ( typeClass ) )
572
602
{
573
603
try
574
604
{
575
- type = ( IType ) Environment . ObjectsFactory . CreateInstance ( typeClass ) ;
605
+ var type = ( IType ) Environment . ObjectsFactory . CreateInstance ( typeClass ) ;
606
+ InjectParameters ( type , parameters ) ;
607
+
608
+ var obsolete = typeClass . GetCustomAttribute < ObsoleteAttribute > ( false ) ;
609
+ if ( obsolete != null )
610
+ {
611
+ _log . Warn ( "{0} ({1}) is obsolete. {2}" , typeClass . FullName , type . Name , obsolete . Message ) ;
612
+ }
613
+
614
+ return type ;
576
615
}
577
- catch ( Exception e )
616
+ catch ( HibernateException )
578
617
{
579
- throw new MappingException ( "Could not instantiate IType " + typeClass . Name + ": " + e , e ) ;
618
+ throw ;
580
619
}
581
- InjectParameters ( type , parameters ) ;
582
-
583
- var obsolete = typeClass . GetCustomAttribute < ObsoleteAttribute > ( false ) ;
584
- if ( obsolete != null )
620
+ catch ( Exception e )
585
621
{
586
- _log . Warn ( "{0} is obsolete. {1}" , typeName , obsolete . Message ) ;
622
+ throw new MappingException ( "Could not instantiate IType " + typeClass . Name + ": " + e , e ) ;
587
623
}
588
- return type ;
589
624
}
625
+
590
626
if ( typeof ( ICompositeUserType ) . IsAssignableFrom ( typeClass ) )
591
627
{
592
628
return new CompositeCustomType ( typeClass , parameters ) ;
593
629
}
630
+
594
631
if ( typeof ( IUserType ) . IsAssignableFrom ( typeClass ) )
595
632
{
596
633
return new CustomType ( typeClass , parameters ) ;
597
634
}
635
+
598
636
if ( typeof ( ILifecycle ) . IsAssignableFrom ( typeClass ) )
599
637
{
600
638
return NHibernateUtil . Entity ( typeClass ) ;
@@ -603,15 +641,12 @@ public static IType HeuristicType(string typeName, IDictionary<string, string> p
603
641
var unwrapped = typeClass . UnwrapIfNullable ( ) ;
604
642
if ( unwrapped . IsEnum )
605
643
{
606
- return ( IType ) Activator . CreateInstance ( typeof ( EnumType < > ) . MakeGenericType ( unwrapped ) ) ;
644
+ return ( IType ) Activator . CreateInstance ( typeof ( EnumType < > ) . MakeGenericType ( unwrapped ) ) ;
607
645
}
608
646
609
647
if ( ! typeClass . IsSerializable )
610
648
return null ;
611
649
612
- if ( typeClassification == TypeClassification . LengthOrScale )
613
- return GetSerializableType ( typeClass , Int32 . Parse ( parsedTypeName [ 1 ] ) ) ;
614
-
615
650
if ( length . HasValue )
616
651
return GetSerializableType ( typeClass , length . Value ) ;
617
652
@@ -690,7 +725,7 @@ public static NullableType GetSerializableType(System.Type serializableType)
690
725
// So we should add the type with its other key in a later operation in order to ensure we cache the same
691
726
// instance for both keys.
692
727
var added = false ;
693
- var type = ( NullableType ) typeByTypeOfName . GetOrAdd (
728
+ var type = typeByTypeOfName . GetOrAdd (
694
729
key ,
695
730
k =>
696
731
{
@@ -703,7 +738,7 @@ public static NullableType GetSerializableType(System.Type serializableType)
703
738
throw new HibernateException ( $ "Another item with the key { type . Name } has already been added to typeByTypeOfName.") ;
704
739
}
705
740
706
- return type ;
741
+ return ( NullableType ) type ;
707
742
}
708
743
709
744
public static NullableType GetSerializableType ( System . Type serializableType , int length )
0 commit comments