让我们从简单的例子开始吧。我和我的团队正在学校的软件项目中工作。我们使用MongoDB来存储产品,我们正在使用接口,因此我们可以在将来更改实现。产品看起来像这样。
interface IProduct
{
long ID { get; set; }
string Name { get; set; }
}
class MongoProduct : IProduct
{
[BsonId]
public long ID { get; set; }
public string Name { get; set; }
}
我们有测试界面。
interface ITestProbe
{
IQueryable<IProduct> FindProducts(Expression<Func<IProduct, bool>> condition);
}
并假设此实现
class MongoRepository : ITestProbe
{
public MongoRepository()
{
_client = new MongoClient();
_server = _client.GetServer();
_db = _server.GetDatabase(_dbName);
_collection = _db.GetCollection(_collectionName);
}
public const string _dbName = "MongoPlayground";
public const string _collectionName = "Products";
protected MongoClient _client;
protected MongoServer _server;
protected MongoDatabase _db;
protected MongoCollection _collection;
public IQueryable<IProduct> FindProducts(System.Linq.Expressions.Expression<Func<IProduct, bool>> condition)
{
return _collection.AsQueryable<MongoProduct>().Where<IProduct>(condition);
}
}
这不起作用,因为“无法确定表达式的序列化信息:p.Name。”当你像这样测试时:
class Program
{
static void GenerateProducts()
{
var _client = new MongoClient();
var _server = _client.GetServer();
var _db = _server.GetDatabase("MongoPlayground");
var _collection = _db.GetCollection("Products");
MongoProduct[] products = new MongoProduct[]{
new MongoProduct(){ID=1,Name="A"},
new MongoProduct(){ID=2,Name="B"},
new MongoProduct(){ID=3,Name="C"},
new MongoProduct(){ID=4,Name="D"}
};
foreach (var p in products)
{
_collection.Insert<MongoProduct>(p);
}
}
static void Main(string[] args)
{
//GenerateProducts();
MongoRepository r = new MongoRepository();
var products = r.FindProducts(p => p.Name == "C");
foreach (var p in products)
{
Console.WriteLine(p.Name);
}
}
}
此问题的解决方案是将Expression从IProduct转换为MongoProduct(示例如何执行此操作是在stackoverflow How do I translate an expression tree of one type to a different expression type?
的其他主题中然后我们可以写:
var switched = Translate<IProduct, MongoProduct>(condition);
return _collection.AsQueryable<MongoProduct>().Where<MongoProduct>(switched);
所以我的问题是,还有另外一种方法吗?我缺少什么?我试图谷歌解决方案但没有发现任何东西。我不明白为什么当MongoProduct是IProduct类型时我们不能在Where函数中使用IProduct。这种“翻译”解决方案对我来说似乎有点笨拙。