@@ -396,6 +396,12 @@ private IMongoQuery BuildComparisonQuery(BinaryExpression binaryExpression)
396
396
return query ;
397
397
}
398
398
399
+ query = BuildTypeComparisonQuery ( variableExpression , operatorType , constantExpression ) ;
400
+ if ( query != null )
401
+ {
402
+ return query ;
403
+ }
404
+
399
405
return BuildComparisonQuery ( variableExpression , operatorType , constantExpression ) ;
400
406
}
401
407
@@ -1251,6 +1257,74 @@ private IMongoQuery BuildStringQuery(MethodCallExpression methodCallExpression)
1251
1257
return null ;
1252
1258
}
1253
1259
1260
+ private IMongoQuery BuildTypeComparisonQuery ( Expression variableExpression , ExpressionType operatorType , ConstantExpression constantExpression )
1261
+ {
1262
+ if ( operatorType != ExpressionType . Equal )
1263
+ {
1264
+ // TODO: support NotEqual?
1265
+ return null ;
1266
+ }
1267
+
1268
+ if ( constantExpression . Type != typeof ( Type ) )
1269
+ {
1270
+ return null ;
1271
+ }
1272
+ var actualType = ( Type ) constantExpression . Value ;
1273
+
1274
+ var methodCallExpression = variableExpression as MethodCallExpression ;
1275
+ if ( methodCallExpression == null )
1276
+ {
1277
+ return null ;
1278
+ }
1279
+ if ( methodCallExpression . Method . Name != "GetType" || methodCallExpression . Object == null )
1280
+ {
1281
+ return null ;
1282
+ }
1283
+ if ( methodCallExpression . Arguments . Count != 0 )
1284
+ {
1285
+ return null ;
1286
+ }
1287
+
1288
+ // TODO: would the object ever not be a ParameterExpression?
1289
+ var parameterExpression = methodCallExpression . Object as ParameterExpression ;
1290
+ if ( parameterExpression == null )
1291
+ {
1292
+ return null ;
1293
+ }
1294
+
1295
+ var serializationInfo = GetSerializationInfo ( parameterExpression ) ;
1296
+ if ( serializationInfo == null )
1297
+ {
1298
+ return null ;
1299
+ }
1300
+ var nominalType = serializationInfo . NominalType ;
1301
+
1302
+ var discriminatorConvention = BsonDefaultSerializer . LookupDiscriminatorConvention ( nominalType ) ;
1303
+ var discriminator = discriminatorConvention . GetDiscriminator ( nominalType , actualType ) ;
1304
+ if ( discriminator == null )
1305
+ {
1306
+ return new QueryDocument ( ) ; // matches everything
1307
+ }
1308
+
1309
+ if ( discriminator . IsBsonArray )
1310
+ {
1311
+ var discriminatorArray = discriminator . AsBsonArray ;
1312
+ var queries = new IMongoQuery [ discriminatorArray . Count + 1 ] ;
1313
+ queries [ 0 ] = Query . Size ( discriminatorConvention . ElementName , discriminatorArray . Count ) ;
1314
+ for ( var i = 0 ; i < discriminatorArray . Count ; i ++ )
1315
+ {
1316
+ queries [ i + 1 ] = Query . EQ ( string . Format ( "{0}.{1}" , discriminatorConvention . ElementName , i ) , discriminatorArray [ i ] ) ;
1317
+ }
1318
+ return Query . And ( queries ) ;
1319
+ }
1320
+ else
1321
+ {
1322
+ return Query . And (
1323
+ Query . Exists ( discriminatorConvention . ElementName + ".0" , false ) , // trick to check that element is not an array
1324
+ Query . EQ ( discriminatorConvention . ElementName , discriminator ) ) ;
1325
+ }
1326
+ }
1327
+
1254
1328
private IMongoQuery BuildTypeIsQuery ( TypeBinaryExpression typeBinaryExpression )
1255
1329
{
1256
1330
var nominalType = typeBinaryExpression . Expression . Type ;
@@ -1260,7 +1334,7 @@ private IMongoQuery BuildTypeIsQuery(TypeBinaryExpression typeBinaryExpression)
1260
1334
var discriminator = discriminatorConvention . GetDiscriminator ( nominalType , actualType ) ;
1261
1335
if ( discriminator == null )
1262
1336
{
1263
- return Query . Not ( "_" ) . Mod ( 1 , 2 ) ; // best query I could come up with that's always true
1337
+ return new QueryDocument ( ) ; // matches everything
1264
1338
}
1265
1339
1266
1340
if ( discriminator . IsBsonArray )
@@ -1355,10 +1429,26 @@ private object ExecuteDistinct(IMongoQuery query)
1355
1429
1356
1430
private BsonSerializationInfo GetSerializationInfo ( Expression expression )
1357
1431
{
1432
+ var parameterExpression = expression as ParameterExpression ;
1433
+ if ( parameterExpression != null )
1434
+ {
1435
+ var serializer = BsonSerializer . LookupSerializer ( parameterExpression . Type ) ;
1436
+ return new BsonSerializationInfo (
1437
+ null , // elementName
1438
+ serializer ,
1439
+ parameterExpression . Type , // nominalType
1440
+ null ) ; // serialization options
1441
+ }
1442
+
1358
1443
// when using OfType the documentType used by the parameter might be a subclass of the DocumentType from the collection
1359
- var parameterExpression = ExpressionParameterFinder . FindParameter ( expression ) ;
1360
- var documentSerializer = BsonSerializer . LookupSerializer ( parameterExpression . Type ) ;
1361
- return GetSerializationInfo ( documentSerializer , expression ) ;
1444
+ parameterExpression = ExpressionParameterFinder . FindParameter ( expression ) ;
1445
+ if ( parameterExpression != null )
1446
+ {
1447
+ var serializer = BsonSerializer . LookupSerializer ( parameterExpression . Type ) ;
1448
+ return GetSerializationInfo ( serializer , expression ) ;
1449
+ }
1450
+
1451
+ return null ;
1362
1452
}
1363
1453
1364
1454
private BsonSerializationInfo GetSerializationInfo ( IBsonSerializer serializer , Expression expression )
0 commit comments