繁体   English   中英

用户定义的过滤器/查询?

[英]User defined filters/queries?

我正在尝试找出一种方法,允许我的应用程序的用户定义自己的查询或可以应用于集合的过滤器。 我想最终提供一个直观的用户界面来创建这些过滤器(请参见下图),但是最初,如果用户必须键入文本查询字符串,那将是可以的。 我还需要能够将这些用户定义的查询序列化为字符串,以便将其与项目的其余信息一起保存。

UI 替代文字 示例 http://dl.dropbox.com/u/113068/filterUI.jpg

我正在寻找您可以从类似SQL查询之类的功能中获取的功能,例如数值条件(小于,大于),字符串条件(包含,以,以结尾)或布尔条件(对或错) )。 我还希望能够使用布尔逻辑(例如OR,AND和NOT)对条件进行分组。

我开始使用诸如NodeFilter,AbsNodeCondition,NodeStringCondition,NodeConditionOrJoin等之类的类从头开始做这件事。但是我感觉我正在重新发明轮子,特别是当有类似Linq的东西可用时,我没有没有机会花费很多时间。

我可以以某种方式允许用户在文本框中输入对对象的Linq查询,然后以编程方式将字符串转换为可以应用于我的集合的真实Linq查询吗? 还是我可以允许用户创建和保存查询的其他方式? 我还需要一种将过滤器/查询序列化为字符串的方法,以便将其与程序的其余信息一起保存。

这不一定是理想的解决方案,但是MetaLinq项目为LINQ表达式类提供了可序列化的包装器。

这是一个在双向序列化表达式后如何重新创建和执行表达式的示例。

首先,我们将现有的lamba表达式序列化为xml文档。

var originalExpr = EditableExpression.CreateEditableExpression<string, bool>(
    str => str.Length > 3);
var serializer = new XmlSerializer(originalExpr.GetType());
string xml;

using (var writer = new StringWriter())
{
    serializer.Serialize(writer, originalExpr);
    xml = writer.ToString();
}

然后,我们将其反序列化,解包装并将其编译回委托中,以准备执行。

EditableExpression newExpr;

using (var reader = new StringReader(xml))
{
    newExpr = (EditableExpression) serializer.Deserialize(reader);
}

var expr = (Expression<Func<string, bool>>) newExpr.ToExpression();
var items = new[] {"one", "two", "three"};
var result = items.Count(expr.Compile());
Debug.Assert(result == 1);

这就是序列化表达式的样子。

<EditableLambdaExpression xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <NodeType>Lambda</NodeType>
  <TypeName>System.Func`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</TypeName>
  <Body xsi:type="EditableBinaryExpression">
    <NodeType>GreaterThan</NodeType>
    <TypeName>System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</TypeName>
    <Left xsi:type="EditableMemberExpression">
      <NodeType>MemberAccess</NodeType>
      <Expression xsi:type="EditableParameterExpression">
        <NodeType>Parameter</NodeType>
        <TypeName>System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</TypeName>
        <Name>str</Name>
      </Expression>
      <MemberName>System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Int32 Length</MemberName>
    </Left>
    <Right xsi:type="EditableConstantExpression">
      <NodeType>Constant</NodeType>
      <Value xsi:type="xsd:int">3</Value>
    </Right>
  </Body>
  <Parameters>
    <EditableExpression xsi:type="EditableParameterExpression">
      <NodeType>Parameter</NodeType>
      <TypeName>System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</TypeName>
      <Name>str</Name>
    </EditableExpression>
  </Parameters>
</EditableLambdaExpression>

不幸的是,System.Linq.Expressions无法序列化,甚至在4.0中也是如此。 如果必须跨越应用程序域边界,则必须诉诸于编写自己的表达式树和访问者以从中生成查询。 否则,在框中表达树会很好。

除此之外,您可能会找到一些适合您需求的动态linq。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM