@@ -159,40 +159,43 @@ private void AllocateParameterAndReplacer()
159
159
var closureType = queryTarget . GetType ( ) ;
160
160
var parameterType = WellKnownOrmTypes . ParameterOfT . CachedMakeGenericType ( closureType ) ;
161
161
var valueMemberInfo = parameterType . GetProperty ( nameof ( Parameter < object > . Value ) , closureType ) ;
162
+ MemberExpression closureAccessor = null ;
162
163
queryParameter = ( Parameter ) System . Activator . CreateInstance ( parameterType , "pClosure" ) ;
164
+ bool ? closureTypeIsClosure = null ;
165
+ FieldInfo [ ] closureTypeFields = null ;
163
166
queryParameterReplacer = new ExtendedExpressionReplacer ( expression => {
164
167
if ( expression . NodeType == ExpressionType . Constant ) {
165
- if ( ( expression as ConstantExpression ) . Value == null ) {
166
- return null ;
167
- }
168
- if ( expression . Type . IsClosure ( ) ) {
169
- if ( expression . Type == closureType ) {
170
- return Expression . MakeMemberAccess ( Expression . Constant ( queryParameter , parameterType ) , valueMemberInfo ) ;
171
- }
172
- else {
173
- throw new NotSupportedException ( string . Format (
174
- Strings . ExExpressionDefinedOutsideOfCachingQueryClosure , expression ) ) ;
175
- }
168
+ if ( ( ( ConstantExpression ) expression ) . Value is null ) {
169
+ return null ;
176
170
}
177
171
178
- if ( closureType . DeclaringType == null ) {
179
- if ( expression . Type . IsAssignableFrom ( closureType ) )
180
- return Expression . MakeMemberAccess ( Expression . Constant ( queryParameter , parameterType ) , valueMemberInfo ) ;
172
+ var expressionType = expression . Type ;
173
+ if ( expressionType . IsClosure ( ) ) {
174
+ return expressionType == closureType
175
+ ? GetClosureAccessor ( )
176
+ : throw new NotSupportedException ( string . Format ( Strings . ExExpressionDefinedOutsideOfCachingQueryClosure , expression ) ) ;
181
177
}
182
- else {
183
- if ( expression . Type . IsAssignableFrom ( closureType ) )
184
- return Expression . MakeMemberAccess ( Expression . Constant ( queryParameter , parameterType ) , valueMemberInfo ) ;
185
- if ( expression . Type . IsAssignableFrom ( closureType . DeclaringType ) ) {
186
- var memberInfo = closureType . TryGetFieldInfoFromClosure ( expression . Type ) ;
187
- if ( memberInfo != null )
188
- return Expression . MakeMemberAccess (
189
- Expression . MakeMemberAccess ( Expression . Constant ( queryParameter , parameterType ) , valueMemberInfo ) ,
190
- memberInfo ) ;
178
+
179
+ if ( expressionType . IsAssignableFrom ( closureType ) )
180
+ return GetClosureAccessor ( ) ;
181
+ if ( closureType . DeclaringType is { } closureTypeDeclaringType && expressionType . IsAssignableFrom ( closureTypeDeclaringType ) ) {
182
+ if ( closureTypeIsClosure is null ) {
183
+ closureTypeIsClosure = closureType . IsClosure ( ) ;
184
+ closureTypeFields = closureTypeIsClosure . Value ? closureType . GetFields ( ) : null ;
185
+ }
186
+
187
+ if ( closureTypeIsClosure . Value
188
+ && closureTypeFields . FirstOrDefault ( field => field . FieldType == expressionType ) is { } memberInfo ) {
189
+ return Expression . MakeMemberAccess ( GetClosureAccessor ( ) , memberInfo ) ;
191
190
}
192
191
}
193
192
}
193
+
194
194
return null ;
195
195
} ) ;
196
+
197
+ MemberExpression GetClosureAccessor ( ) =>
198
+ closureAccessor ??= Expression . MakeMemberAccess ( Expression . Constant ( queryParameter , parameterType ) , valueMemberInfo ) ;
196
199
}
197
200
198
201
private ParameterizedQuery GetCachedQuery ( ) =>
0 commit comments