我有一个类似于下面的界面:
public IEnumerable<IDocument> Search(Predicate<IDocument> predicate) { ... }其中IDocument如下所示:
public interface IDocument
{
string Id {get; set;}
string Title {get; set;}
...
}我将要实现一个文档提供程序,在该提供程序中,我必须分解谓词的内容并提取属性,以便为文档数据库生成SQL字符串,而我们目前没有到该文档数据库的OR/M映射。例如:我想知道用户是按ID搜索还是按标题搜索,这样我就知道我是否可以按ID搜索或必须对标题执行LIKE搜索。
我一直在大量使用LINQ,但这是我第一次坐在管道的另一端……我已经阅读了一些关于表达式、树和反射的内容,但这些部分还没有到位。如何(如果?)我是否可以分解/反射谓词,以便获得可以连接到SQL字符串中的参数列表?我正在寻找类似于这个草图的东西:
public IEnumerable<IDocument> Search(Predicate<IDocument> predicate)
{
string id = DoSomeMagic(predicate, "Id");
string title = DoSomeMagic(predicate, "Title");
if (!string.isNullOrEmpty(id))
...make ID search
else
...search by title
}免责声明:提供者是为一个内部遗留系统准备在今年秋天进行替换,这使得内联SQL成为一个合适的选择;o)
发布于 2010-03-09 22:13:40
你不能轻易地反省这个谓词。也许您应该考虑将您的设计更改为更特别的谓词类型,即更具体的谓词接口:
public interface IDocument
{
string Id {get; set;}
string Title {get; set;}
}
public class SearchCriteria
{
public Nullable<int> Id;
public string Title;
}
public IEnumerable<IDocument> Search(SearchCriteria predicate)
{
if (predicate.Id.HasValue)
//...make ID search
else if (!string.IsNullOrEmpty(predicate.Title))
//...search by title
else
// other kind of search
}用属性替换公共字段,将搜索逻辑放在SearchCriteria (例如.GetResult()或.GetSQLQuery())中,假设您知道所有可用的搜索条件,这可能适合您的系统。
发布于 2010-03-09 22:00:15
您不能使用谓词或委托来做到这一点。它们是经过编译的,不可能得到关于它做了什么的信息。为此,您确实需要Expression树,但是自己解析可能会很困难。你最好使用O/RM工具。
例如,当您将表达式与LINQ to SQL一起使用时,构建您的搜索方法将是轻而易举的:
public IEnumerable<Document> Search(
Expression<Func<Document, bool>> predicate)
{
using (db = new DocumentDataContext())
{
return db.Documents.Where(predicate).ToArray();
}
}发布于 2010-03-09 22:31:03
您需要将您的方法声明为接受Expression>。这个表达式可以内省(尽管可以有很多不同的东西)。
尝试在LinqPad中运行以下代码(LinqPad提供了转储扩展方法,可以很好地将表达式可视化)
void Main()
{
show(x=>x.Length==5);
}
void show(Expression<Predicate<string>> e){
e.Dump();
}您可以通过首先调用Compile来执行表达式
https://stackoverflow.com/questions/2409442
复制相似问题