1+ using System . Reflection ;
2+ using Ydb . Sdk . Value ;
3+
4+ namespace Ydb . Sdk . Ado . BulkUpsert ;
5+
6+ internal static class TypedValueFactory
7+ {
8+ public static TypedValue FromObjects < T > ( IReadOnlyCollection < T > rows )
9+ {
10+ if ( rows . Count == 0 )
11+ throw new ArgumentException ( "Rows collection is empty." , nameof ( rows ) ) ;
12+
13+ var props = typeof ( T ) . GetProperties ( BindingFlags . Instance | BindingFlags . Public )
14+ . Where ( p => p . CanRead ) . ToArray ( ) ;
15+
16+ var structs = new List < YdbValue > ( rows . Count ) ;
17+
18+ foreach ( var row in rows )
19+ {
20+ var members = new Dictionary < string , YdbValue > ( props . Length ) ;
21+ foreach ( var p in props )
22+ members [ p . Name ] = ToYdbValue ( p . GetValue ( row ) , p . PropertyType ) ;
23+
24+ structs . Add ( YdbValue . MakeStruct ( members ) ) ;
25+ }
26+
27+ var list = YdbValue . MakeList ( structs ) ;
28+ return list . GetProto ( ) ;
29+ }
30+
31+ private static YdbValue ToYdbValue ( object ? value , global ::System . Type clr )
32+ {
33+ if ( value is null ) return MakeOptional ( clr ) ;
34+
35+ if ( clr == typeof ( bool ) ) return ( YdbValue ) ( bool ) value ;
36+ if ( clr == typeof ( sbyte ) ) return ( YdbValue ) ( sbyte ) value ;
37+ if ( clr == typeof ( short ) ) return ( YdbValue ) ( short ) value ;
38+ if ( clr == typeof ( int ) ) return ( YdbValue ) ( int ) value ;
39+ if ( clr == typeof ( long ) ) return ( YdbValue ) ( long ) value ;
40+ if ( clr == typeof ( byte ) ) return ( YdbValue ) ( byte ) value ;
41+ if ( clr == typeof ( ushort ) ) return ( YdbValue ) ( ushort ) value ;
42+ if ( clr == typeof ( uint ) ) return ( YdbValue ) ( uint ) value ;
43+ if ( clr == typeof ( ulong ) ) return ( YdbValue ) ( ulong ) value ;
44+ if ( clr == typeof ( float ) ) return ( YdbValue ) ( float ) value ;
45+ if ( clr == typeof ( double ) ) return ( YdbValue ) ( double ) value ;
46+ if ( clr == typeof ( decimal ) ) return ( YdbValue ) ( decimal ) value ;
47+ if ( clr == typeof ( DateTime ) ) return YdbValue . MakeTimestamp ( ( DateTime ) value ) ;
48+ if ( clr == typeof ( TimeSpan ) ) return ( YdbValue ) ( TimeSpan ) value ;
49+ if ( clr == typeof ( Guid ) ) return YdbValue . MakeUuid ( ( Guid ) value ) ;
50+ if ( clr == typeof ( string ) ) return YdbValue . MakeUtf8 ( ( string ) value ) ;
51+ if ( clr == typeof ( byte [ ] ) ) return YdbValue . MakeString ( ( byte [ ] ) value ) ;
52+
53+ throw new NotSupportedException ( $ "Type '{ clr . FullName } ' is not supported.") ;
54+ }
55+
56+ private static YdbValue MakeOptional ( global ::System . Type clr )
57+ {
58+ var t = Nullable . GetUnderlyingType ( clr ) ?? clr ;
59+
60+ if ( t == typeof ( bool ) ) return YdbValue . MakeOptionalBool ( ) ;
61+ if ( t == typeof ( sbyte ) ) return YdbValue . MakeOptionalInt8 ( ) ;
62+ if ( t == typeof ( short ) ) return YdbValue . MakeOptionalInt16 ( ) ;
63+ if ( t == typeof ( int ) ) return YdbValue . MakeOptionalInt32 ( ) ;
64+ if ( t == typeof ( long ) ) return YdbValue . MakeOptionalInt64 ( ) ;
65+ if ( t == typeof ( byte ) ) return YdbValue . MakeOptionalUint8 ( ) ;
66+ if ( t == typeof ( ushort ) ) return YdbValue . MakeOptionalUint16 ( ) ;
67+ if ( t == typeof ( uint ) ) return YdbValue . MakeOptionalUint32 ( ) ;
68+ if ( t == typeof ( ulong ) ) return YdbValue . MakeOptionalUint64 ( ) ;
69+ if ( t == typeof ( float ) ) return YdbValue . MakeOptionalFloat ( ) ;
70+ if ( t == typeof ( double ) ) return YdbValue . MakeOptionalDouble ( ) ;
71+ if ( t == typeof ( decimal ) ) return YdbValue . MakeOptionalDecimal ( ) ;
72+ if ( t == typeof ( DateTime ) ) return YdbValue . MakeOptionalTimestamp ( ) ;
73+ if ( t == typeof ( TimeSpan ) ) return YdbValue . MakeOptionalInterval ( ) ;
74+ if ( t == typeof ( Guid ) ) return YdbValue . MakeOptionalUuid ( ) ;
75+ if ( t == typeof ( string ) ) return YdbValue . MakeOptionalUtf8 ( ) ;
76+ if ( t == typeof ( byte [ ] ) ) return YdbValue . MakeOptionalString ( ) ;
77+
78+ throw new NotSupportedException ( $ "Null for '{ t . FullName } ' is not supported.") ;
79+ }
80+ }
0 commit comments