@@ -25,6 +25,8 @@ internal static class QueryHelper
2525 {
2626 private sealed class OwnerWrapper < TOwner >
2727 {
28+ public static readonly Type GenericDef = typeof ( OwnerWrapper < > ) ;
29+
2830 public TOwner Owner { get ; set ; }
2931
3032 public OwnerWrapper ( TOwner owner )
@@ -76,22 +78,29 @@ public static bool IsDirectEntitySetQuery(Expression entitySet)
7678 return false ;
7779 var wrapper = ( ( MemberExpression ) owner ) . Expression ;
7880 return wrapper . NodeType == ExpressionType . Constant
79- && wrapper . Type . IsGenericType
80- && wrapper . Type . GetGenericTypeDefinition ( ) == typeof ( OwnerWrapper < > ) ;
81+ && wrapper . Type . IsOwnerWrapper ( ) ;
8182 }
8283
8384 public static Expression CreateDirectEntitySetQuery ( EntitySetBase entitySet )
8485 {
8586 // A hack making expression to look like regular parameter
8687 // (ParameterExtractor.IsParameter => true)
8788 var owner = entitySet . Owner ;
89+ var ownerType = owner . TypeInfo . UnderlyingType ;
8890 var wrapper = Activator . CreateInstance (
89- typeof ( OwnerWrapper < > ) . MakeGenericType ( owner . GetType ( ) ) , owner ) ;
90- var wrappedOwner = Expression . Property ( Expression . Constant ( wrapper ) , " Owner" ) ;
91+ OwnerWrapper < int > . GenericDef . MakeGenericType ( ownerType ) , owner ) ;
92+ var wrappedOwner = Expression . Property ( Expression . Constant ( wrapper ) , nameof ( OwnerWrapper < int > . Owner ) ) ;
9193 if ( ! entitySet . Field . IsDynamicallyDefined ) {
9294 return Expression . Property ( wrappedOwner , entitySet . Field . UnderlyingProperty ) ;
9395 }
94- var indexers = owner . GetType ( ) . GetProperties ( BindingFlags . Instance | BindingFlags . NonPublic | BindingFlags . Public )
96+ //fast way to get indexer getter method
97+ var indexerGetter = ownerType . GetMethod ( Reflection . WellKnown . IndexerPropertyGetterName , BindingFlags . Instance | BindingFlags . NonPublic | BindingFlags . Public ) ;
98+ if ( indexerGetter . Attributes . HasFlag ( MethodAttributes . SpecialName )
99+ && ( indexerGetter . DeclaringType == WellKnownOrmTypes . Persistent || indexerGetter . DeclaringType == WellKnownOrmTypes . Entity ) )
100+ return Expression . Convert ( Expression . Call ( Expression . Constant ( owner ) , indexerGetter , new [ ] { Expression . Constant ( entitySet . Field . Name ) } ) , entitySet . Field . ValueType ) ;
101+
102+ // old-fashion slow way, if something went wrong
103+ var indexers = ownerType . GetProperties ( BindingFlags . Instance | BindingFlags . NonPublic | BindingFlags . Public )
95104 . Where ( p => p . GetIndexParameters ( ) . Any ( ) )
96105 . Select ( p => p . GetGetMethod ( ) ) ;
97106 return Expression . Convert ( Expression . Call ( Expression . Constant ( owner ) , indexers . Single ( ) , new [ ] { Expression . Constant ( entitySet . Field . Name ) } ) , entitySet . Field . ValueType ) ;
@@ -191,7 +200,7 @@ public static void TryAddConvarianceCast(ref Expression source, Type baseType)
191200 public static Type GetSequenceElementType ( Type type )
192201 {
193202 var sequenceType = type . GetGenericInterface ( WellKnownInterfaces . EnumerableOfT ) ;
194- return sequenceType != null ? sequenceType . GetGenericArguments ( ) [ 0 ] : null ;
203+ return sequenceType ? . GetGenericArguments ( ) [ 0 ] ;
195204 }
196205
197206 private static Expression BuildExpressionForFieldRecursivly ( FieldInfo field , Expression parameter )
@@ -202,5 +211,9 @@ private static Expression BuildExpressionForFieldRecursivly(FieldInfo field, Exp
202211 }
203212 return Expression . Property ( parameter , field . DeclaringField . UnderlyingProperty ) ;
204213 }
214+
215+ private static bool IsOwnerWrapper ( this Type type ) =>
216+ ( type . MetadataToken ^ OwnerWrapper < int > . GenericDef . MetadataToken ) == 0
217+ && ReferenceEquals ( type . Module , OwnerWrapper < int > . GenericDef . Module ) ;
205218 }
206219}
0 commit comments