获取谓词<t>属性信息</t>

时间:2010-03-09 13:52:56

标签: c# reflection

我有一个类似于以下内容的界面:

public IEnumerable<IDocument> Search(Predicate<IDocument> predicate) { ... }

IDocument看起来像这样:

public interface IDocument 
{
    string Id {get; set;}
    string Title {get; set;}
    ...
}

我即将实现一个文档提供程序,我必须分解Predicate的内容并提取属性,以便为我们当前没有OR / M映射的文档数据库创建一个SQL字符串。例如:我想知道用户是按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)

3 个答案:

答案 0 :(得分:3)

您不能使用谓词或委托来执行此操作。它们被编译,无法获得有关它的功能的信息。你真的需要Expression树,但是自己解析这个可能很困难。你最好使用O / RM工具。

例如,当您将Expression与LINQ to SQL一起使用时,构建搜索方法将变得轻而易举:

public IEnumerable<Document> Search(
    Expression<Func<Document, bool>> predicate) 
{
    using (db = new DocumentDataContext())
    {
        return db.Documents.Where(predicate).ToArray();
    }
}

答案 1 :(得分:1)

你不能轻易地反省谓词。也许您应该考虑将您的设计更改为更具特色的谓词类型,更具体的谓词界面:

    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()),这可能适合您的系统,假设您可以了解所有可用的搜索条件。

答案 2 :(得分:0)

您需要将方法声明为接受表达式&gt;代替。这个表达式可以被反思(虽然它可以有很多不同的东西)。

尝试在LinqPad中运行以下命令(LinqPad提供了转储扩展方法,可以很好地显示表达式)

void Main()
{
    show(x=>x.Length==5);
}

void show(Expression<Predicate<string>> e){
    e.Dump();
}

您可以先调用Compile

来执行表达式