微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 是否可以为字符串实现ExpressionTree.GreaterThan等,以便LINQ可以使用它

我今天早上( Query my model on a range of values)看到了一个似乎由( https://stackoverflow.com/a/1447926/195550)回答的问题,但是那里的整个情况让我对更广泛的解决方案感兴趣.

我希望能够使用Jon Skeet的答案来实现在非sql生成的环境中使用字符串键的Betweent,但看起来字符串没有实现GreaterThan,Lessthan,GreaterThanorEqual,LessthanorEqual运算符的事实进入Linq能够构建执行此操作所必需的表达式树的方式.

>我意识到可以使用Compareto方法进行查询来完成此任务,但我真的很喜欢查询的优雅.Between(v => v.StringKey,“abc”,“hjk”)表达式.
>我查看了System.Linq.Expression程序集,看到它正在寻找名为’op_GreaterThan’的方法,例如对于GreaterThan操作,但我不知道

>我是否可以为字符串实现此功能(知道我无法为字符串扩展实际的’>’运算符)
>如何构建正确的方法签名.

>我创建了以下示例和测试,显示了Between扩展方法对字符串键不起作用的位置.

如果可以为字符串键实现它将是非常优雅的.有人对如何做到这一点有任何建议或见解吗?

来自Jon Skeet的操作符之间,增加了包容性标志

public static class BetweenExtension
{
    public static IQueryable<TSource> Between<TSource,TKey>(
        this IQueryable<TSource> source,Expression<Func<TSource,TKey>> keySelector,TKey low,TKey high,bool inclusive = true) where TKey : IComparable<TKey>
    {
        var key = Expression.Invoke(keySelector,keySelector.Parameters.ToArray());

        var lowerBound = (inclusive)
                  ? Expression.GreaterThanorEqual(key,Expression.Constant(low))
                  : Expression.GreaterThan(key,Expression.Constant(low));

        var upperBound = (inclusive)
                  ? Expression.LessthanorEqual(key,Expression.Constant(high))
                  : Expression.Lessthan(key,Expression.Constant(high));

        var and = Expression.AndAlso(lowerBound,upperBound);
        var lambda = Expression.Lambda<Func<TSource,bool>>(
                        and,keySelector.Parameters);

        return source.Where(lambda);
    }
}

使用“int”键进行上述工作测试

[TestFixture]
public class BetweenIntTests
{
    public class SampleEntityInt
    {
        public int SampleSearchKey { get; set; }
    }

    private IQueryable<SampleEntityInt> BuildSampleEntityInt(params int[] values)
    {
        return values.Select(
               value => 
               new SampleEntityInt() { SampleSearchKey = value }).AsQueryable();
    }

    [Test]
    public void BetweenIntInclusive()
    {
        var sampleData = BuildSampleEntityInt(1,3,10,11,12,15);
        var query = sampleData.Between(s => s.SampleSearchKey,10);
        Assert.AreEqual(2,query.Count());
    }

    [Test]
    public void BetweenIntnotinclusive()
    {
        var sampleData = BuildSampleEntityInt(1,2,false);
        Assert.AreEqual(2,query.Count());
    }
}

使用“字符串”键进行上述非工作测试

[TestFixture]
public class BetweenStringsTests
{

    public class SampleEntityString
    {
        public string SampleSearchKey { get; set; }
    }

    private IQueryable<SampleEntityString> BuildSampleEntityString(params int[] values)
    {
        return values.Select(
               value =>
               new SampleEntityString() {SampleSearchKey = value.ToString() }).AsQueryable();
    }

    [Test]
    public void BetweenStringInclusive()
    {
        var sampleData = BuildSampleEntityString(1,"3","10");
        Assert.AreEqual(2,query.Count());
    }

    [Test]
    public void BetweenStringnotinclusive()
    {
        var sampleData = BuildSampleEntityString(1,"2","11",query.Count());
    }
}

解决方法

您必须调用string.Compareto方法作为表达式树的一部分.然后,您可以测试其结果.要查看它的外观,请在调试器中查看以下值:

Expression<<Func<string,bool>> filter = str => str.Compareto("abc") > 0;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐