Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可比较的通用液体_C#_Linq_Generics_Iqueryable - Fatal编程技术网

C# 可比较的通用液体

C# 可比较的通用液体,c#,linq,generics,iqueryable,C#,Linq,Generics,Iqueryable,所以我试图创建一个函数,它接受一个IQueryable,并在该IQueryable中包含一个DateTime属性,然后返回一个IQueryable,并与另一个DateTime进行比较 目前,我必须为几个不同的函数执行此操作,并且此代码可能会发生更改,因此我希望此代码能够通用地应用于IQueryable: FMGQueryableSet = FMGQueryableSet.Where(t => t.Created.Day >= StartDate.Value.Day)

所以我试图创建一个函数,它接受一个IQueryable,并在该IQueryable中包含一个DateTime属性,然后返回一个IQueryable,并与另一个DateTime进行比较

目前,我必须为几个不同的函数执行此操作,并且此代码可能会发生更改,因此我希望此代码能够通用地应用于IQueryable:

  FMGQueryableSet = FMGQueryableSet.Where(t => t.Created.Day >= StartDate.Value.Day)
                               .Where(t => t.Created.Month >= StartDate.Value.Month)
                               .Where(t => t.Created.Year >= StartDate.Value.Year);
相反,我希望能够做到这一点:

FMGQueryableSet = SetDateCompare(FMGQueryableSet, t=> t.Created, StartDate, false)
方法存根看起来像这样,但是我不知道如何将传入的属性绑定到IQueryable

public IQueryable<T> SetDateCompare<T>(IQueryable<T> OriginalQuery, Expression<Func<DateTime>> QueryProperty, DateTime ComparisonDate, bool isGreaterThan = true) 
    where T : class
    {
        if(isGreaterThan)
        {
            OriginalQuery = OriginalQuery.Where(QueryProperty >= ComparisonDate.Day)
                            .Where(QueryProperty >= ComparisonDate.Month)
                            .Where(QueryProperty >= ComparisonDate.Year);
        }
        else
        {
            OriginalQuery = OriginalQuery.Where(QueryProperty <= ComparisonDate.Day)
                           .Where(QueryProperty <= ComparisonDate.Month)
                           .Where(QueryProperty <= ComparisonDate.Year);

        }
        return OriginalQuery;

    }
public IQueryable SetDateCompare(IQueryable原始查询、表达式查询属性、日期时间比较数据、布尔值大于等于true)
T:在哪里上课
{
如果(大于)
{
OriginalQuery=OriginalQuery.Where(QueryProperty>=comparisonadate.Day)
.Where(QueryProperty>=comparisonadate.Month)
其中(查询属性>=比较数据年份);
}
其他的
{

OriginalQuery=OriginalQuery.Where(QueryPropertyt=>t.创建了所需调用的一部分,它是一个lambda表达式,表示从类型t获取日期时间的函数,因此此函数的参数应该是Func

考虑到这一点,您应该尝试以下方法:

public IQueryable<T> SetDateCompare<T>(IQueryable<T> OriginalQuery, Func<T,DateTime> getDateFunc, DateTime ComparisonDate, bool isGreaterThan = true)
where T : class
{
    if (isGreaterThan)
    {
        OriginalQuery = OriginalQuery.Where(t => getDateFunc(t).Day >= ComparisonDate.Day)
                        .Where(t => getDateFunc(t).Month >= ComparisonDate.Month)
                        .Where(t => getDateFunc(t).Year >= ComparisonDate.Year);
    }
    else
    {
        OriginalQuery = OriginalQuery.Where(t => getDateFunc(t).Day <= ComparisonDate.Day)
                        .Where(t => getDateFunc(t).Month  <= ComparisonDate.Month)
                        .Where(t => getDateFunc(t).Year  <= ComparisonDate.Year);

    }
    return OriginalQuery;

}
public IQueryable SetDateCompare(IQueryable OriginalQuery,Func getDateFunc,DateTime comparisondata,bool isGreaterThan=true)
T:在哪里上课
{
如果(大于)
{
OriginalQuery=OriginalQuery.Where(t=>getDateFunc(t.Day>=comparisonadate.Day)
.Where(t=>getDateFunc(t).Month>=ComparisonDate.Month)
其中(t=>getDateFunc(t).Year>=ComparisonDate.Year);
}
其他的
{

OriginalQuery=OriginalQuery.Where(t=>getDateFunc(t).Day getDateFunc(t).Month getDateFunc(t).Year假设您真的想要显示不寻常的比较逻辑,下面是如何实现的。如果您需要不同的比较逻辑,只需更改表达式ymdCompareLess和YMDComparRegreater

要做的第一件事是创建一个可以传递给where子句的新表达式。您希望能够传递一个表达式,该表达式指示要比较的属性和要在比较中使用的日期值

我在下面为小于比较和大于比较创建了两个表达式。根据为isGreaterThan传入的值,我们为大于比较或小于比较选择表达式

我正在使用我在StackOverflow上第一次看到的替换访问者模式,通过用其他表达式替换所有原始参数来创建一个新的表达式

选择要使用的表达式后,将替换该表达式的参数。第一个参数v1将替换为QueryProperty主体。假设您传递了类似于
v=>v.CreatedDate
,则该表达式的主体将是
CreatedDate

第二个参数v2将替换为包含传入日期值的表达式常量

结果将是创建的表达式看起来像
v=>v.CreatedDate.Day>=(新的日期时间(2005,2,3)).Day
,其中
v
是您传入的表达式中的参数

然后我们创建一个lambda表达式,创建的表达式作为主体,传入的参数作为参数

最后,我们使用新的lambda表达式作为过滤器调用.Where方法并返回结果

Expression<Func<DateTime, DateTime, bool>> ymdCompareLess = (v1, v2) => v1.Day <= v2.Day && v1.Month <= v2.Month && v1.Year <= v2.Year;
Expression<Func<DateTime, DateTime, bool>> ymdCompareGreater = (v1, v2) => v1.Day >= v2.Day && v1.Month >= v2.Month && v1.Year >= v2.Year;

public IQueryable<T> SetDateCompare<T>(IQueryable<T> OriginalQuery, Expression<Func<T, DateTime>> QueryProperty, DateTime ComparisonDate, bool isGreaterThan = true)
        where T : class
{
    LambdaExpression comparisonExpression = isGreaterThan ? ymdCompareGreater : ymdCompareLess;

    var replaceVisitor = new ReplaceVisitor(
        comparisonExpression.Parameters.ToArray(),
        new[] { QueryProperty.Body, Expression.Constant(ComparisonDate) }
        );

    var whereBody = replaceVisitor.Visit(comparisonExpression.Body);

    var whereClause = Expression.Lambda<Func<T, bool>>(whereBody, QueryProperty.Parameters);

    return OriginalQuery.Where(whereClause);
}

private class ReplaceVisitor : ExpressionVisitor
{
    Expression[] _from;
    Expression[] _to;
    public ReplaceVisitor(Expression[] from, Expression[] to)
    {
        this._from = from;
        this._to = to;
    }

    public override Expression Visit(Expression node)
    {
        var idx = Array.IndexOf(_from, node);

        if (idx > -1)
        {
            return _to[idx];
        }
        return base.Visit(node);
    }
}
表达式YMDComparess=(v1,v2)=>v1.Day=v2.Month&&v1.Year>=v2.Year;
公共IQueryable SetDateCompare(IQueryable原始查询、表达式QueryProperty、日期时间比较数据、布尔值大于等于true)
T:在哪里上课
{
lambdexpression comparisonExpression=大于?Ymdcomparegrater:Ymdcomparess;
var replaceVisitor=新的replaceVisitor(
comparisonExpression.Parameters.ToArray(),
新[]{QueryProperty.Body,Expression.Constant(ComparisonData)}
);
var whereBody=replaceVisitor.Visit(comparisonExpression.Body);
var whereClause=Expression.Lambda(whereBody,QueryProperty.Parameters);
返回原始查询。Where(Where子句);
}
私有类替换访问者:ExpressionVisitor
{
表达式[]来自;
表达[]_至;
公共访问者(表达式[]从,表达式[]到)
{
这个;
这个;
}
公共重写表达式访问(表达式节点)
{
var idx=Array.IndexOf(_from,node);
如果(idx>-1)
{
返回到[idx];
}
返回基地访问(节点);
}
}

谢谢,我现在正在测试它,不过我很确定这应该可以!传入第二个变量最简单的方法是什么,Lamba的明显不工作Ambda应该可以,什么不工作?你在调用中指定了类型了吗?SetDateComparesrry我的intellisense被破坏了。现在可以了哦,我明白了,表达式修复了苏?如果是这样,我会编辑我的回答。他们也检查一下!如果你愿意,这将帮助你扩展linq,我相信你的逻辑中有一个根本性的缺陷。假设创建日期为2014-01-01,起始日期为2013-12-31。第一个
位置将过滤掉它,因为1<31。