将匿名类型转换为新的 C# 7 元组类型 [英] Convert anonymous type to new C# 7 tuple type
问题描述
新版本的 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屋!