根据不同的条件创建匿名类型并将其强制转换为类

本文关键字:转换 类型 条件 创建 | 更新日期: 2023-09-27 17:50:32

我有这个问题有一段时间了,但是今天我达到了临界点,我请求你的帮助。

假设我有这样的代码:
var query = DbContext.Table.Where(x => x.z == true).Select(x => new { x.a, x.b, x.c });
foreach(var item in query)
{
    // Do the work
}

我结束了这个匿名类型,一切都很好。现在出现了一些东西,使我对Where子句有条件,因此我必须根据条件进行不同的查询这是我真正感到沮丧的地方:

if(something)
{
    var query = DbContext.Table.Where(x => x.z == true && x.zz == false).Select(x => new { x.a, x.b, x.c });
    foreach(var item in query)
    {
        // Do the work
    }
}
else
{
    var query = DbContext.Table.Where(x => x.z == true).Select(x => new { x.a, x.b, x.c });
    foreach(var item in query)
    {
        // Do the work
    }
}

因为在foreach循环中要做的功是完全相同的,我不应该重复它。

所以,我没有使用匿名类型,而是声明了一个新类,并尝试这样做:
class MyQuery
{
    public int a { get; set; }
    public string b { get; set; }
    public decimal? c { get; set; }
}
IQueryable<MyQuery> query = null;
if(something)
{
    query = (IQueryable<MyQuery>)DbContext.Table.Where(x => x.z == true && x.zz == false).Select(x => new { x.a, x.b, x.c });
}
else
{
    query = (IQueryable<MyQuery>)DbContext.Table.Where(x => x.z == true).Select(x => new { x.a, x.b, x.c });
}
foreach(var item in query)
{
    // Do the work
}

但是现在我有一个'System.InvalidCastException'抛出,因为我仍然得到一个匿名类型,显然它不能被强制转换到我的类。

为了维护,我想避免代码的重复,但我不知道该怎么做。我觉得我在这里遗漏了一些基本的东西,但找不到,所以欢迎你的帮助和感激。

非常感谢你的帮助

根据不同的条件创建匿名类型并将其强制转换为类

你太复杂了:

IQueryable<MyQuery> query = DbContext.Table;
if (something)
{
    query = query.Where(x => x.z == true && x.zz == false)
}
else
{
    query = query.Where(x => x.z == true);
}
var result = query.Select(x => new { x.a, x.b, x.c });
foreach (var item in result)
{
    // Do the work
}

.Where()方法不会改变查询的"类型"!

注意这是合法的:

var query = DbContext.Table.Select(x => new { x.a, x.b, x.c });
if (something)
{
    query = DbContext.Table.Where(x => x.z == true && x.zz == false).Select(x => new { x.a, x.b, x.c });
}
else
{
    query = DbContext.Table.Where(x => x.z == true).Select(x => new { x.a, x.b, x.c });
}
foreach (var item in query)
{
    // Do the work
}

我使用了这样一个事实,即在同一程序集中具有相同参数的匿名类型(参数名称相同,参数类型相同,参数数量相同)由c#编译器"统一"。我使用var query = DbContext.Table.Select(x => new { x.a, x.b, x.c });这一行只是为了"赋予"var变量类型。然后我用其他查询完全覆盖查询,因为各种.Select(x => new { x.a, x.b, x.c });"产生"相同(匿名)类型的对象。

您可以修改Where条件以匹配大小写。通过这种方式,您不再需要担心重复的代码或创建仅在此方法上使用的另一个类。

var query = DbContext.Table.Where(x => something && (x.z == true && x.zz == false) || !something && (x.z == true)).Select(x => new { x.a, x.b, x.c });
foreach(var item in query)
{
    // Do the work
}

或者你可以像@Rawling提到的那样添加一个三元比较

var query = DbContext.Table.Where(x => something ? (x.z == true && x.zz == false) : (x.z == true)).Select(x => new { x.a, x.b, x.c });
foreach(var item in query)
{
    // Do the work
}