@@ -396,7 +396,7 @@ module internal Impl =
396
396
let mutable systemValueTupleException = null
397
397
398
398
let reflectedValueTuple n =
399
- try
399
+ try
400
400
#if FX_ ASSEMBLYLOADBYSTRING
401
401
let a = Assembly.Load( " System.ValueTuple" )
402
402
#else
@@ -522,7 +522,7 @@ module internal Impl =
522
522
let tysA = tyargs.[ 0 .. tupleEncField-1 ]
523
523
let tyB = tyargs.[ tupleEncField]
524
524
Array.append tysA ( getTupleTypeInfo tyB)
525
- else
525
+ else
526
526
tyargs
527
527
528
528
let orderTupleProperties ( props : PropertyInfo []) =
@@ -548,34 +548,73 @@ module internal Impl =
548
548
haveNames = expectNames)
549
549
#endif
550
550
props
551
-
551
+
552
+ let orderTupleFields ( fields : FieldInfo []) =
553
+ // The tuple fields are of the form:
554
+ // Item1
555
+ // ..
556
+ // Item1, Item2, ..., Item<maxTuple-1>
557
+ // Item1, Item2, ..., Item<maxTuple-1>, Rest
558
+ // The PropertyInfo may not come back in order, so ensure ordering here.
559
+ #if FX_ ATLEAST_ PORTABLE
560
+ #else
561
+ assert ( maxTuple < 10 ) // Alphasort will only works for upto 9 items: Item1, Item10, Item2, Item3, ..., Item9, Rest
562
+ #endif
563
+ let fields = fields |> Array.sortBy ( fun fi -> fi.Name) // they are not always in alphabetic order
564
+ #if FX_ ATLEAST_ PORTABLE
565
+ #else
566
+ assert ( fields.Length <= maxTuple)
567
+ assert ( let haveNames = fields |> Array.map ( fun fi -> fi.Name)
568
+ let expectNames = Array.init fields.Length ( fun i -> let j = i+ 1 // index j = 1,2,..,fields.Length <= maxTuple
569
+ if j< maxTuple then " Item" + string j
570
+ elif j= maxTuple then " Rest"
571
+ else ( assert false ; " " )) // dead code under prior assert, props.Length <= maxTuple
572
+ haveNames = expectNames)
573
+ #endif
574
+ fields
575
+
552
576
let getTupleConstructorMethod ( typ : Type , bindingFlags ) =
553
- let props = typ.GetProperties() |> orderTupleProperties
577
+ let ctor =
578
+ if typ.IsValueType then
579
+ let fields = typ.GetFields() |> orderTupleFields
554
580
#if FX_ ATLEAST_ PORTABLE
555
- let ctor = typ.GetConstructor( props |> Array.map ( fun p -> p.PropertyType))
556
- ignore bindingFlags
557
- #else
558
- let ctor = typ.GetConstructor( BindingFlags.Instance ||| bindingFlags, null , props |> Array.map ( fun p -> p.PropertyType), null )
559
- #endif
560
- match ctor with
561
- | null -> raise <| ArgumentException( SR.GetString1( SR.invalidTupleTypeConstructorNotDefined, typ.FullName))
562
- | _ -> ()
563
- ctor
564
-
581
+ ignore bindingFlags
582
+ typ.GetConstructor( fields |> Array.map ( fun fi -> fi.FieldType))
583
+ #else
584
+ typ.GetConstructor( BindingFlags.Instance ||| bindingFlags, null , fields |> Array.map ( fun fi -> fi.FieldType), null )
585
+ #endif
586
+ else
587
+ let props = typ.GetProperties() |> orderTupleProperties
588
+ #if FX_ ATLEAST_ PORTABLE
589
+ ignore bindingFlags
590
+ typ.GetConstructor( props |> Array.map ( fun p -> p.PropertyType))
591
+ #else
592
+ typ.GetConstructor( BindingFlags.Instance ||| bindingFlags, null , props |> Array.map ( fun p -> p.PropertyType), null )
593
+ #endif
594
+ match ctor with
595
+ | null -> raise <| ArgumentException( SR.GetString1( SR.invalidTupleTypeConstructorNotDefined, typ.FullName))
596
+ | _ -> ()
597
+ ctor
598
+
565
599
let getTupleCtor ( typ : Type , bindingFlags ) =
566
600
let ctor = getTupleConstructorMethod( typ, bindingFlags)
567
601
( fun ( args : obj []) ->
568
602
#if FX_ ATLEAST_ PORTABLE
569
603
ctor.Invoke( args))
570
604
#else
571
605
ctor.Invoke( BindingFlags.InvokeMethod ||| BindingFlags.Instance ||| bindingFlags, null , args, null ))
572
- #endif
606
+ #endif
573
607
574
608
let rec getTupleReader ( typ : Type ) =
575
609
let etys = typ.GetGenericArguments()
576
610
// Get the reader for the outer tuple record
577
- let props = typ.GetProperties( instancePropertyFlags ||| BindingFlags.Public) |> orderTupleProperties
578
- let reader = ( fun ( obj : obj ) -> props |> Array.map ( fun prop -> prop.GetValue( obj, null )))
611
+ let reader =
612
+ if typ.IsValueType then
613
+ let fields = ( typ.GetFields( instancePropertyFlags ||| BindingFlags.Public) |> orderTupleFields)
614
+ (( fun ( obj : obj ) -> fields |> Array.map ( fun field -> field.GetValue( obj))))
615
+ else
616
+ let props = ( typ.GetProperties( instancePropertyFlags ||| BindingFlags.Public) |> orderTupleProperties)
617
+ (( fun ( obj : obj ) -> props |> Array.map ( fun prop -> prop.GetValue( obj, null ))))
579
618
if etys.Length < maxTuple
580
619
then reader
581
620
else
@@ -585,7 +624,7 @@ module internal Impl =
585
624
let directVals = reader obj
586
625
let encVals = reader2 directVals.[ tupleEncField]
587
626
Array.append directVals.[ 0 .. tupleEncField-1 ] encVals)
588
-
627
+
589
628
let rec getTupleConstructor ( typ : Type ) =
590
629
let etys = typ.GetGenericArguments()
591
630
let maker1 = getTupleCtor ( typ, BindingFlags.Public)
@@ -606,20 +645,25 @@ module internal Impl =
606
645
else
607
646
maker1, Some( etys.[ tupleEncField])
608
647
609
- let getTupleReaderInfo ( typ : Type , index : int ) =
648
+ let getTupleReaderInfo ( typ : Type , index : int ) =
610
649
if index < 0 then invalidArg " index" ( SR.GetString2( SR.tupleIndexOutOfRange, typ.FullName, index.ToString()))
611
- let props = typ.GetProperties( instancePropertyFlags ||| BindingFlags.Public) |> orderTupleProperties
612
- let get index =
613
- if index >= props.Length then invalidArg " index" ( SR.GetString2( SR.tupleIndexOutOfRange, typ.FullName, index.ToString()))
614
- props.[ index]
615
-
650
+
651
+ let get index =
652
+ if typ.IsValueType then
653
+ let props = typ.GetProperties( instancePropertyFlags ||| BindingFlags.Public) |> orderTupleProperties
654
+ if index >= props.Length then invalidArg " index" ( SR.GetString2( SR.tupleIndexOutOfRange, typ.FullName, index.ToString()))
655
+ props.[ index]
656
+ else
657
+ let props = typ.GetProperties( instancePropertyFlags ||| BindingFlags.Public) |> orderTupleProperties
658
+ if index >= props.Length then invalidArg " index" ( SR.GetString2( SR.tupleIndexOutOfRange, typ.FullName, index.ToString()))
659
+ props.[ index]
660
+
616
661
if index < tupleEncField then
617
- get index, None
662
+ get index, None
618
663
else
619
664
let etys = typ.GetGenericArguments()
620
665
get tupleEncField, Some( etys.[ tupleEncField], index-( maxTuple-1 ))
621
-
622
-
666
+
623
667
//-----------------------------------------------------------------
624
668
// FUNCTION DECOMPILATION
625
669
0 commit comments