@@ -159,15 +159,42 @@ public static bool IsDapperAttribute(AttributeData attrib)
159159
160160 public static bool IsMissingOrObjectOrDynamic ( ITypeSymbol ? type ) => type is null || type . SpecialType == SpecialType . System_Object || type . TypeKind == TypeKind . Dynamic ;
161161
162- internal static bool IsDynamicParameters ( ITypeSymbol ? type )
162+ internal static bool IsDynamicParameters ( ITypeSymbol ? type , out bool needsConstruction )
163163 {
164+ needsConstruction = false ;
164165 if ( type is null || type . SpecialType != SpecialType . None ) return false ;
165166 if ( IsBasicDapperType ( type , Types . DynamicParameters )
166167 || IsNestedSqlMapperType ( type , Types . IDynamicParameters , TypeKind . Interface ) ) return true ;
167168 foreach ( var i in type . AllInterfaces )
168169 {
169170 if ( IsNestedSqlMapperType ( i , Types . IDynamicParameters , TypeKind . Interface ) ) return true ;
170171 }
172+
173+ // Dapper also treats anything IEnumerable<string,object[?]> as dynamic parameters
174+ if ( type . ImplementsIEnumerable ( out var found ) && found is INamedTypeSymbol { Arity : 1 } iet
175+ && iet . TypeArguments [ 0 ] is INamedTypeSymbol
176+ {
177+ Name : "KeyValuePair" , Arity : 2 , ContainingType : null ,
178+ ContainingNamespace :
179+ {
180+ Name : "Generic" ,
181+ ContainingNamespace :
182+ {
183+ Name : "Collections" ,
184+ ContainingNamespace :
185+ {
186+ Name : "System" ,
187+ ContainingNamespace . IsGlobalNamespace : true
188+ }
189+ }
190+ }
191+ } kvp
192+ && kvp . TypeArguments [ 0 ] . SpecialType == SpecialType . System_String
193+ && kvp . TypeArguments [ 1 ] . SpecialType == SpecialType . System_Object )
194+ {
195+ needsConstruction = true ;
196+ return true ;
197+ }
171198 return false ;
172199 }
173200
@@ -419,7 +446,7 @@ public readonly struct ElementMember
419446 /// Order of member in constructor parameter list (starts from 0).
420447 /// </summary>
421448 public int ? ConstructorParameterOrder { get ; }
422-
449+
423450 /// <summary>
424451 /// Order of member in factory method parameter list (starts from 0).
425452 /// </summary>
@@ -452,10 +479,10 @@ public ElementMember(
452479 {
453480 _dbValue = dbValue ;
454481 _flags = flags ;
455-
482+
456483 Member = member ;
457484 Kind = kind ;
458-
485+
459486 ConstructorParameterOrder = constructorParameterOrder ;
460487 FactoryMethodParameterOrder = factoryMethodParameterOrder ;
461488 }
@@ -493,7 +520,7 @@ public enum ConstructorResult
493520 FailMultipleExplicit ,
494521 FailMultipleImplicit
495522 }
496-
523+
497524 public enum FactoryMethodResult
498525 {
499526 // note that implicit isn't a thing here
@@ -513,12 +540,12 @@ internal static FactoryMethodResult ChooseFactoryMethod(ITypeSymbol? typeSymbol,
513540 {
514541 return FactoryMethodResult . NoneFound ;
515542 }
516-
543+
517544 var staticMethods = typeSymbol
518- . GetMethods ( method =>
545+ . GetMethods ( method =>
519546 method . IsStatic &&
520547 SymbolEqualityComparer . Default . Equals ( method . ReturnType , typeSymbol ) &&
521- method . DeclaredAccessibility == Accessibility . Public
548+ method . DeclaredAccessibility == Accessibility . Public
522549 )
523550 ? . ToArray ( ) ;
524551 if ( staticMethods ? . Length == 0 )
@@ -541,7 +568,7 @@ internal static FactoryMethodResult ChooseFactoryMethod(ITypeSymbol? typeSymbol,
541568
542569 return factoryMethod is null ? FactoryMethodResult . NoneFound : FactoryMethodResult . SuccessSingleExplicit ;
543570 }
544-
571+
545572 /// <summary>
546573 /// Builds a collection of type constructors, which are NOT:
547574 /// a) parameterless
@@ -613,7 +640,8 @@ internal static ConstructorResult ChooseConstructor(ITypeSymbol? typeSymbol, out
613640 ContainingNamespace :
614641 {
615642 Name : "Runtime" ,
616- ContainingNamespace : {
643+ ContainingNamespace :
644+ {
617645 Name : "System" ,
618646 ContainingNamespace . IsGlobalNamespace : true
619647 }
@@ -630,7 +658,7 @@ internal static ConstructorResult ChooseConstructor(ITypeSymbol? typeSymbol, out
630658 // ruled out by signature
631659 continue ;
632660 }
633-
661+
634662 if ( constructor is not null )
635663 {
636664 return ConstructorResult . FailMultipleImplicit ;
@@ -704,7 +732,7 @@ internal static ImmutableArray<ElementMember> GetMembers(bool forParameters, ITy
704732 int ? constructorParameterOrder = constructorParameters ? . TryGetValue ( member . Name , out var constructorParameter ) == true
705733 ? constructorParameter . Order
706734 : null ;
707-
735+
708736 int ? factoryMethodParamOrder = factoryMethodParameters ? . TryGetValue ( member . Name , out var factoryMethodParam ) == true
709737 ? factoryMethodParam . Order
710738 : null ;
@@ -1018,12 +1046,12 @@ public static bool TryGetConstantValueWithSyntax<T>(IOperation val, out T? value
10181046 case StringSyntaxKind . ConcatenatedString :
10191047 case StringSyntaxKind . InterpolatedString :
10201048 case StringSyntaxKind . FormatString :
1021- {
1022- value = default ! ;
1023- syntax = null ;
1024- syntaxKind = stringSyntaxKind ;
1025- return false ;
1026- }
1049+ {
1050+ value = default ! ;
1051+ syntax = null ;
1052+ syntaxKind = stringSyntaxKind ;
1053+ return false ;
1054+ }
10271055 }
10281056 }
10291057
@@ -1096,25 +1124,25 @@ internal static bool IsCommand(INamedTypeSymbol type)
10961124 while ( type . SpecialType != SpecialType . System_Object )
10971125 {
10981126 if ( type is
1099- {
1100- Name : nameof ( DbCommand ) ,
1101- ContainingType : null ,
1102- Arity : 0 ,
1103- IsGenericType : false ,
1104- ContainingNamespace :
11051127 {
1106- Name : "Common" ,
1128+ Name : nameof ( DbCommand ) ,
1129+ ContainingType : null ,
1130+ Arity : 0 ,
1131+ IsGenericType : false ,
11071132 ContainingNamespace :
11081133 {
1109- Name : "Data " ,
1134+ Name : "Common " ,
11101135 ContainingNamespace :
11111136 {
1112- Name : "System" ,
1113- ContainingNamespace . IsGlobalNamespace : true ,
1137+ Name : "Data" ,
1138+ ContainingNamespace :
1139+ {
1140+ Name : "System" ,
1141+ ContainingNamespace . IsGlobalNamespace : true ,
1142+ }
11141143 }
11151144 }
1116- }
1117- } )
1145+ } )
11181146 {
11191147 return true ;
11201148 }
0 commit comments