将匿名类型转换为新的 C# 7 元组类型 [英] Convert anonymous type to new C# 7 tuple type

查看:22
本文介绍了将匿名类型转换为新的 C# 7 元组类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

新版本的 C# 已经出现,具有有用的新功能 Tuple Types:

The new version of C# is there, with the useful new feature Tuple Types:

public IQueryable<T> Query<T>();

public (int id, string name) GetSomeInfo() {
    var obj = Query<SomeType>()
        .Select(o => new {
            id = o.Id,
            name = o.Name,
        })
        .First();

    return (id: obj.id, name: obj.name);
}

有没有办法将我的匿名类型对象 obj 转换为我想要返回的元组,而无需逐个映射属性(假设属性的名称匹配)?

Is there a way to convert my anonymous type object obj to the tuple that I want to return without mapping property by property (assuming that the names of the properties match)?

上下文在 ORM 中,我的 SomeType 对象有很多其他属性,它被映射到一个包含很多列的表.我想做一个只带 ID 和 NAME 的查询,所以我需要将匿名类型转换为元组,或者我需要 ORM Linq 提供者知道如何理解元组并将属性相关列放在 SQL 选择子句中.

The context is in a ORM, my SomeType object has a lot of other properties and it is mapped to a table with lot of columns. I wanna do a query that brings just ID and NAME, so I need to convert the anonymous type into a tuple, or I need that an ORM Linq Provider know how to understand a tuple and put the properties related columns in the SQL select clause.

推荐答案

简短的回答是否定的,在当前的 C#7 形式中,没有框架内的方法可以逐字完成您的目标,因为您想要完成:

The short answer is no, in the current form of C#7 there is no in-framework way to accomplish your goals verbatim, since you want to accomplish:

  • Linq 到实体
  • 映射到列的子集
  • 通过直接映射到 C#7 元组来避免从自定义或匿名类型到 C#7 元组的逐个属性映射.

因为 Query<SomeType> 公开了一个 IQueryable,所以必须对表达式树进行任何类型的投影 .Select(x => new {}).

Because Query<SomeType> exposes an IQueryable, any sort of projection must be made to an expression tree .Select(x => new {}).

有一个 open roslyn issue 用于添加此支持,但它没有还存在.

There is an open roslyn issue for adding this support, but it doesn't exist yet.

因此,在添加此支持之前,您可以手动从匿名类型映射到元组,或者返回整个记录并将结果直接映射到元组以避免两次映射,但这显然是低效的.

As a result, until this support is added, you can either manually map from an anonymous type to a tuple, or return the entire record and map the result to a tuple directly to avoid two mappings, but this is obviously inefficient.

虽然由于缺乏支持以及无法在 .Select() 投影中使用参数化构造函数,此限制目前已纳入 Linq-to-Entities,但 Linq-to-NHibernate 和Linq-to-Sql 允许以在 .Select() 投影中创建新 System.Tuple 的形式进行破解,然后返回带有 .ToValueTuple() 扩展方法:

While this restriction is currently baked into Linq-to-Entities due to a lack of support and the inability to use parametered constructors in a .Select() projection, both Linq-to-NHibernate and Linq-to-Sql allow for a hack in the form of creating a new System.Tuple in the .Select() projection, and then returning a ValueTuple with the .ToValueTuple() extension method:

public IQueryable<T> Query<T>();

public (int id, string name) GetSomeInfo() {
    var obj = Query<SomeType>()
        .Select(o => new System.Tuple<int, string>(o.Id, o.Name))
        .First();

    return obj.ToValueTuple();
}

由于 System.Tuple 可以映射到表达式,因此您可以从表中返回数据子集,并允许框架处理映射到您的 C#7 元组.然后,您可以使用您选择的任何命名约定来解构参数:

Since System.Tuple can be mapped to an expression, you can return a subset of data from your table and allow the framework to handle mapping to your C#7 tuple. You can then deconstruct the arguments with any naming convention you choose:

(int id, string customName) info = GetSomeInfo();
Console.Write(info.customName);

这篇关于将匿名类型转换为新的 C# 7 元组类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆