@@ -35,7 +35,30 @@ public static class Decoder
35
35
/// <param name="value">The FaunaDB value to be decoded</param>
36
36
/// <typeparam name="T">The type name in which the value should be decoded</typeparam>
37
37
public static T Decode < T > ( Value value ) =>
38
- ( T ) DecoderImpl . Decode ( value , typeof ( T ) ) ;
38
+ ( T ) new DecoderImpl ( NamingStrategy . Default ) . Decode ( value , typeof ( T ) , null ) ;
39
+
40
+ /// <summary>
41
+ /// Decode the FaunaDB value into the specified type T.
42
+ /// </summary>
43
+ /// <example>
44
+ /// Decode<int>(LongV.Of(10)) => 10
45
+ /// Decode<double>(DoubleV.Of(3.14)) => 3.14
46
+ /// Decode<bool>(BooleanV.True) => true
47
+ /// Decode<object>(NullV.Instance) => null
48
+ /// Decode<string>(StringV.Of("a string")) => "a string"
49
+ /// Decode<int[]>(ArrayV.Of(1, 2)) => new int[] { 1, 2 }
50
+ /// Decode<List<int>>(ArrayV.Of(1, 2)) => new List<int>> { 1, 2 }
51
+ /// Decode<byte[]>(new ByteV(1, 2)) => new byte[] { 1, 2 }
52
+ /// Decode<DateTime>(new TimeV("2000-01-01T01:10:30.123Z")) => new DateTime(2000, 1, 1, 1, 10, 30, 123)
53
+ /// Decode<DateTime>(new DateV("2001-01-01")) => new DateTime(2001, 1, 1)
54
+ /// Decode<User>(ObjectV.With("user_name", "john", "password", "s3cr3t")) => new User("john", "s3cr3t")
55
+ /// </example>
56
+ /// <returns>An instance of type T</returns>
57
+ /// <param name="value">The FaunaDB value to be decoded</param>
58
+ /// <param name="namingStrategy">The naming strategy to use</param>
59
+ /// <typeparam name="T">The type name in which the value should be decoded</typeparam>
60
+ public static T Decode < T > ( Value value , NamingStrategy namingStrategy ) =>
61
+ ( T ) new DecoderImpl ( namingStrategy ) . Decode ( value , typeof ( T ) , null ) ;
39
62
40
63
/// <summary>
41
64
/// Decode the FaunaDB value into the type specified in the argument.
@@ -57,21 +80,57 @@ public static T Decode<T>(Value value) =>
57
80
/// <param name="value">The FaunaDB value to be decoded</param>
58
81
/// <param name="dstType">The type in which the value should be decoded</param>
59
82
public static object Decode ( Value value , Type dstType ) =>
60
- DecoderImpl . Decode ( value , dstType ) ;
83
+ new DecoderImpl ( NamingStrategy . Default ) . Decode ( value , dstType , null ) ;
84
+
85
+ /// <summary>
86
+ /// Decode the FaunaDB value into the type specified in the argument.
87
+ /// </summary>
88
+ /// <example>
89
+ /// Decode(LongV.Of(10), typeof(int)) => 10
90
+ /// Decode(DoubleV.Of(3.14), typeof(double)) => 3.14
91
+ /// Decode(BooleanV.True, typeof(bool)) => true
92
+ /// Decode(NullV.Instance, typeof(object)) => null
93
+ /// Decode(StringV.Of("a string"), typeof(string)) => "a string"
94
+ /// Decode(ArrayV.Of(1, 2), typeof(int[])) => new int[] { 1, 2 }
95
+ /// Decode(ArrayV.Of(1, 2), typeof(List<int>>)) => new List<int>> { 1, 2 }
96
+ /// Decode(new ByteV(1, 2), typeof(byte[])) => new byte[] { 1, 2 }
97
+ /// Decode(new TimeV("2000-01-01T01:10:30.123Z"), typeof(DateTime)) => new DateTime(2000, 1, 1, 1, 10, 30, 123)
98
+ /// Decode(new DateV("2001-01-01"), typeof(DateTime)) => new DateTime(2001, 1, 1)
99
+ /// Decode(ObjectV.With("user_name", "john", "password", "s3cr3t"), typeof(User)) => new User("john", "s3cr3t")
100
+ /// </example>
101
+ /// <returns>An instance of type specified in the argument</returns>
102
+ /// <param name="value">The FaunaDB value to be decoded</param>
103
+ /// <param name="dstType">The type in which the value should be decoded</param>
104
+ /// <param name="namingStrategy">The naming strategy to use</param>
105
+ public static object Decode ( Value value , Type dstType , NamingStrategy namingStrategy ) =>
106
+ new DecoderImpl ( namingStrategy ) . Decode ( value , dstType , null ) ;
61
107
}
62
108
63
109
internal class DecoderImpl
64
110
{
65
111
private static readonly Dictionary < Type , Converter > converters = new Dictionary < Type , Func < Value , object > > ( ) ;
66
112
private static readonly ReaderWriterLockSlim locker = new ReaderWriterLockSlim ( ) ;
67
113
68
- private static InvalidCastException invalidCast ( object value , Type to )
114
+ private NamingStrategy namingStrategy ;
115
+
116
+ private InvalidCastException invalidCast ( object value , Type to )
69
117
{
70
118
var from = value ? . GetType ( ) ;
71
119
return new InvalidCastException ( $ "Invalid cast from '{ from } ' to '{ to } '.") ;
72
120
}
73
121
74
- public static object Decode ( Value value , Type dstType , Type forceType = null )
122
+ public DecoderImpl ( NamingStrategy decoderNamingStrategy )
123
+ {
124
+ namingStrategy = decoderNamingStrategy ;
125
+ }
126
+
127
+ public static object Decode ( Value value , Type dstType , Type forceType , NamingStrategy namingStrategy )
128
+ {
129
+ return new DecoderImpl ( namingStrategy )
130
+ . Decode ( value , dstType , forceType ) ;
131
+ }
132
+
133
+ public object Decode ( Value value , Type dstType , Type forceType = null )
75
134
{
76
135
if ( value == NullV . Instance && dstType == typeof ( Value ) )
77
136
{
@@ -86,7 +145,7 @@ public static object Decode(Value value, Type dstType, Type forceType = null)
86
145
return DecodeIntern ( value , dstType , forceType ) ;
87
146
}
88
147
89
- private static object DecodeIntern ( Value value , Type dstType , Type forceType = null )
148
+ private object DecodeIntern ( Value value , Type dstType , Type forceType = null )
90
149
{
91
150
if ( typeof ( Value ) . IsAssignableFrom ( dstType ) )
92
151
{
@@ -215,7 +274,7 @@ private static object DecodeIntern(Value value, Type dstType, Type forceType = n
215
274
throw invalidCast ( value , dstType ) ;
216
275
}
217
276
218
- private static IEnumerable FromSet ( Value value , Type type )
277
+ private IEnumerable FromSet ( Value value , Type type )
219
278
{
220
279
if ( ! ( value is ArrayV ) )
221
280
{
@@ -242,7 +301,7 @@ private static IEnumerable FromSet(Value value, Type type)
242
301
return set ;
243
302
}
244
303
245
- private static IList FromEnumerable ( Value value , Type type )
304
+ private IList FromEnumerable ( Value value , Type type )
246
305
{
247
306
if ( ! ( value is ArrayV ) )
248
307
{
@@ -270,7 +329,7 @@ private static IList FromEnumerable(Value value, Type type)
270
329
return ret ;
271
330
}
272
331
273
- private static IDictionary FromDictionary ( Value value , Type type )
332
+ private IDictionary FromDictionary ( Value value , Type type )
274
333
{
275
334
if ( ! ( value is ObjectV ) )
276
335
{
@@ -299,7 +358,7 @@ private static IDictionary FromDictionary(Value value, Type type)
299
358
return ret ;
300
359
}
301
360
302
- private static Array FromArray ( Value value , Type type )
361
+ private Array FromArray ( Value value , Type type )
303
362
{
304
363
var elementType = type . GetElementType ( ) ;
305
364
@@ -320,7 +379,7 @@ private static Array FromArray(Value value, Type type)
320
379
return ret ;
321
380
}
322
381
323
- private static object ToNumber < R > ( Value value )
382
+ private object ToNumber < R > ( Value value )
324
383
{
325
384
var ll = value as ScalarValue < long > ;
326
385
if ( ll != null )
@@ -343,19 +402,19 @@ private static object ToNumber<R>(Value value)
343
402
throw invalidCast ( value , typeof ( R ) ) ;
344
403
}
345
404
346
- private static string ToString ( Value value ) =>
405
+ private string ToString ( Value value ) =>
347
406
FromScalar < string > ( value , typeof ( string ) ) ;
348
407
349
- private static bool ToBoolean ( Value value ) =>
408
+ private bool ToBoolean ( Value value ) =>
350
409
FromScalar < bool > ( value , typeof ( bool ) ) ;
351
410
352
- private static DateTime ToDateTime ( Value value ) =>
411
+ private DateTime ToDateTime ( Value value ) =>
353
412
FromScalar < DateTime > ( value , typeof ( DateTime ) ) ;
354
413
355
- private static byte [ ] ToByteArray ( Value value ) =>
414
+ private byte [ ] ToByteArray ( Value value ) =>
356
415
FromScalar < byte [ ] > ( value , typeof ( byte [ ] ) ) ;
357
416
358
- private static T FromScalar < T > ( Value value , Type type )
417
+ private T FromScalar < T > ( Value value , Type type )
359
418
{
360
419
var scalar = value as ScalarValue < T > ;
361
420
@@ -367,7 +426,7 @@ private static T FromScalar<T>(Value value, Type type)
367
426
return scalar . Value ;
368
427
}
369
428
370
- private static object ToEnum ( Value value , Type dstType )
429
+ private object ToEnum ( Value value , Type dstType )
371
430
{
372
431
Converter converter ;
373
432
@@ -396,7 +455,7 @@ private static object ToEnum(Value value, Type dstType)
396
455
return converter . Invoke ( value ) ;
397
456
}
398
457
399
- private static object FromObject ( Value value , Type dstType )
458
+ private object FromObject ( Value value , Type dstType )
400
459
{
401
460
Converter converter ;
402
461
@@ -430,7 +489,7 @@ private static object ThrowError(Value value, Type dstType)
430
489
throw new InvalidOperationException ( $ "Enumeration value '{ ( ( StringV ) value ) . Value } ' not found in { dstType } ") ;
431
490
}
432
491
433
- private static Converter CreateEnumConverter ( Type dstType )
492
+ private Converter CreateEnumConverter ( Type dstType )
434
493
{
435
494
var objExpr = Expression . Parameter ( typeof ( Value ) , "obj" ) ;
436
495
var varExpr = Expression . Variable ( dstType , "output" ) ;
@@ -457,7 +516,7 @@ private static Converter CreateEnumConverter(Type dstType)
457
516
. Compile ( ) ;
458
517
}
459
518
460
- private static SwitchCase CreateSwitchCase ( Enum enumValue )
519
+ private SwitchCase CreateSwitchCase ( Enum enumValue )
461
520
{
462
521
var dstType = enumValue . GetType ( ) ;
463
522
var enumName = Enum . GetName ( dstType , enumValue ) ;
@@ -472,7 +531,7 @@ private static SwitchCase CreateSwitchCase(Enum enumValue)
472
531
typeof ( string ) ) ) ;
473
532
}
474
533
475
- private static Converter CreateConverter ( Type dstType )
534
+ private Converter CreateConverter ( Type dstType )
476
535
{
477
536
var creator = GetCreator ( dstType ) ;
478
537
@@ -495,7 +554,7 @@ private static Converter CreateConverter(Type dstType)
495
554
return FromConstructor ( constructor , dstType ) ;
496
555
}
497
556
498
- private static MethodInfo GetCreator ( Type dstType )
557
+ private MethodInfo GetCreator ( Type dstType )
499
558
{
500
559
var methods = dstType
501
560
. GetMethods ( BindingFlags . Public | BindingFlags . Static )
@@ -514,7 +573,7 @@ private static MethodInfo GetCreator(Type dstType)
514
573
return null ;
515
574
}
516
575
517
- private static ConstructorInfo GetConstructor ( Type dstType )
576
+ private ConstructorInfo GetConstructor ( Type dstType )
518
577
{
519
578
var constructors = dstType
520
579
. GetConstructors ( )
@@ -533,19 +592,19 @@ private static ConstructorInfo GetConstructor(Type dstType)
533
592
return dstType . GetConstructor ( Type . EmptyTypes ) ;
534
593
}
535
594
536
- private static Expression AssignProperties ( Expression objExpr , Expression varExpr , Type dstType , IEnumerable < string > ignoreProperties )
595
+ private Expression AssignProperties ( Expression objExpr , Expression varExpr , Type dstType , IEnumerable < string > ignoreProperties )
537
596
{
538
597
var fields = dstType
539
598
. GetAllFields ( )
540
- . Where ( f => ! ignoreProperties . Contains ( f . GetName ( ) ) )
599
+ . Where ( f => ! ignoreProperties . Contains ( f . GetName ( namingStrategy ) ) )
541
600
. Where ( f => ! f . Has < CompilerGeneratedAttribute > ( ) && ! f . Has < FaunaIgnoreAttribute > ( ) )
542
- . Select ( f => Expression . Assign ( Expression . Field ( varExpr , f ) , CallDecode ( CallGetValue ( objExpr , f , f . FieldType ) , f . FieldType , f . GetOverrideType ( ) ) ) ) ;
601
+ . Select ( f => Expression . Assign ( Expression . Field ( varExpr , f ) , CallDecode ( CallGetValue ( objExpr , f , f . FieldType ) , f . FieldType , f . GetOverrideType ( ) , namingStrategy ) ) ) ;
543
602
544
603
var properties = dstType
545
604
. GetProperties ( )
546
- . Where ( p => ! ignoreProperties . Contains ( p . GetName ( ) ) )
605
+ . Where ( p => ! ignoreProperties . Contains ( p . GetName ( namingStrategy ) ) )
547
606
. Where ( p => p . CanWrite && ! p . Has < FaunaIgnoreAttribute > ( ) )
548
- . Select ( p => Expression . Assign ( Expression . MakeMemberAccess ( varExpr , p ) , CallDecode ( CallGetValue ( objExpr , p , p . PropertyType ) , p . PropertyType , p . GetOverrideType ( ) ) ) ) ;
607
+ . Select ( p => Expression . Assign ( Expression . MakeMemberAccess ( varExpr , p ) , CallDecode ( CallGetValue ( objExpr , p , p . PropertyType ) , p . PropertyType , p . GetOverrideType ( ) , namingStrategy ) ) ) ;
549
608
550
609
var concat = fields . Concat ( properties ) ;
551
610
@@ -554,16 +613,16 @@ private static Expression AssignProperties(Expression objExpr, Expression varExp
554
613
: ( Expression ) Expression . Empty ( ) ;
555
614
}
556
615
557
- private static Converter Create ( Func < IEnumerable < Expression > , Expression > creatorExpr , ParameterInfo [ ] parameters , Type dstType )
616
+ private Converter Create ( Func < IEnumerable < Expression > , Expression > creatorExpr , ParameterInfo [ ] parameters , Type dstType )
558
617
{
559
618
var objExpr = Expression . Parameter ( typeof ( Value ) , "obj" ) ;
560
619
var varExpr = Expression . Variable ( dstType , "output" ) ;
561
620
var target = Expression . Label ( dstType ) ;
562
621
563
622
var parametersExpr = parameters
564
- . Select ( p => CallDecode ( CallGetValue ( objExpr , p ) , p . ParameterType , p . GetOverrideType ( ) ) ) ;
623
+ . Select ( p => CallDecode ( CallGetValue ( objExpr , p ) , p . ParameterType , p . GetOverrideType ( ) , namingStrategy ) ) ;
565
624
566
- var ignoreProperties = parameters . Select ( p => p . GetName ( ) ) ;
625
+ var ignoreProperties = parameters . Select ( p => p . GetName ( namingStrategy ) ) ;
567
626
568
627
var block = Expression . Block (
569
628
new ParameterExpression [ ] { varExpr } ,
@@ -588,7 +647,7 @@ private static Converter Create(Func<IEnumerable<Expression>, Expression> creato
588
647
* return output;
589
648
* }
590
649
*/
591
- private static Converter FromValueType ( Type dstType )
650
+ private Converter FromValueType ( Type dstType )
592
651
{
593
652
return Create (
594
653
_ => Expression . New ( dstType ) ,
@@ -611,7 +670,7 @@ private static Converter FromValueType(Type dstType)
611
670
* return output;
612
671
* }
613
672
*/
614
- private static Converter FromConstructor ( ConstructorInfo constructor , Type dstType )
673
+ private Converter FromConstructor ( ConstructorInfo constructor , Type dstType )
615
674
{
616
675
return Create (
617
676
p => Expression . New ( constructor , p ) ,
@@ -634,7 +693,7 @@ private static Converter FromConstructor(ConstructorInfo constructor, Type dstTy
634
693
* return output;
635
694
* }
636
695
*/
637
- private static Converter FromMethodCreator ( MethodInfo creator , Type dstType )
696
+ private Converter FromMethodCreator ( MethodInfo creator , Type dstType )
638
697
{
639
698
return Create (
640
699
p => Expression . Call ( creator , p ) ,
@@ -646,23 +705,23 @@ private static Converter FromMethodCreator(MethodInfo creator, Type dstType)
646
705
/*
647
706
* Decode( objExpr, type )
648
707
*/
649
- private static Expression CallDecode ( Expression objExpr , Type type , Type overrideType = null )
708
+ private Expression CallDecode ( Expression objExpr , Type type , Type overrideType , NamingStrategy namingStrategy )
650
709
{
651
710
var decodeMethod = typeof ( DecoderImpl ) . GetMethod (
652
- "Decode" , BindingFlags . Static | BindingFlags . Public , null , new Type [ ] { typeof ( Value ) , typeof ( Type ) , typeof ( Type ) } , null
711
+ "Decode" , BindingFlags . Static | BindingFlags . Public , null , new Type [ ] { typeof ( Value ) , typeof ( Type ) , typeof ( Type ) , typeof ( NamingStrategy ) } , null
653
712
) ;
654
713
655
714
var decodeExpr = Expression . Call (
656
715
decodeMethod ,
657
- new Expression [ ] { objExpr , Expression . Constant ( type ) , Expression . Constant ( overrideType , typeof ( Type ) ) }
716
+ new Expression [ ] { objExpr , Expression . Constant ( type ) , Expression . Constant ( overrideType , typeof ( Type ) ) , Expression . Constant ( namingStrategy , typeof ( NamingStrategy ) ) }
658
717
) ;
659
718
660
719
return type . GetTypeInfo ( ) . IsValueType
661
720
? Expression . Unbox ( decodeExpr , type )
662
721
: Expression . Convert ( decodeExpr , type ) ;
663
722
}
664
723
665
- private static Expression CallGetValue ( Expression objExpr , MemberInfo member , Type memberType )
724
+ private Expression CallGetValue ( Expression objExpr , MemberInfo member , Type memberType )
666
725
{
667
726
var field = member . GetCustomAttribute < FaunaFieldAttribute > ( ) ;
668
727
var defaultValue = field != null ? Encoder . Encode ( field . DefaultValue ) : null ;
@@ -683,10 +742,10 @@ private static Expression CallGetValue(Expression objExpr, MemberInfo member, Ty
683
742
return Expression . Constant ( defaultValue , typeof ( Value ) ) ;
684
743
}
685
744
686
- return CallGetValue ( objExpr , member . GetName ( ) , defaultValue ) ;
745
+ return CallGetValue ( objExpr , member . GetName ( namingStrategy ) , defaultValue ) ;
687
746
}
688
747
689
- private static Expression CallGetValue ( Expression objExpr , ParameterInfo parameter )
748
+ private Expression CallGetValue ( Expression objExpr , ParameterInfo parameter )
690
749
{
691
750
var field = parameter . GetCustomAttribute < FaunaFieldAttribute > ( ) ;
692
751
var hasDefaultValue = field != null && field . DefaultValue != null ;
@@ -710,13 +769,13 @@ private static Expression CallGetValue(Expression objExpr, ParameterInfo paramet
710
769
return Expression . Constant ( defaultValue , typeof ( Value ) ) ;
711
770
}
712
771
713
- return CallGetValue ( objExpr , parameter . GetName ( ) , defaultValue ) ;
772
+ return CallGetValue ( objExpr , parameter . GetName ( namingStrategy ) , defaultValue ) ;
714
773
}
715
774
716
775
/*
717
776
* GetValue( objExpr, property, defaultValue )
718
777
*/
719
- private static Expression CallGetValue ( Expression objExpr , string property , Value defaultValue )
778
+ private Expression CallGetValue ( Expression objExpr , string property , Value defaultValue )
720
779
{
721
780
var getValueMethod = typeof ( DecoderImpl ) . GetMethod (
722
781
"GetValue" , BindingFlags . Static | BindingFlags . NonPublic , null , new Type [ ] { typeof ( ObjectV ) , typeof ( string ) , typeof ( Value ) } , null
0 commit comments