如何在不定义新类型的情况下从函数返回LINQ查询的匿名类型列表?
解决方案
不需要定义新类型的前提下,你可以通过以下两种方式实现:
1. 返回IEnumerable<dynamic>
这是最直接且实用的方案,利用dynamic类型绕过编译时类型检查,让程序在运行时解析匿名类型的属性:
public IEnumerable<dynamic> GetTheList() { var list = (from t in db.Transactions from tr in db.TransactionRules.Where(tr => EF.Functions.Like(t.Description, tr.Pattern)).DefaultIfEmpty() select new { t.TransactionId, t.Description, t.Note, t.Amount, t.Date, tr.Pattern, TransactionRuleId = tr.TransactionRuleId != null ? tr.TransactionRuleId : 0, TransactionRule = tr.TransactionRuleId != null ? tr : null, TransactionClass = tr.TransactionClass != null ? tr.TransactionClass : (t.TransactionClassId > 0 ? tc2 : new TransactionClass()), Final = t.Amount > 0 ? t.Amount : (tr.TransactionClass?.Percentage > 0 ? (t.Amount / 100) * tr.TransactionClass.Percentage : t.Amount), }); // 若需立即执行查询(避免延迟加载导致的数据库访问时机问题),可调用ToList() return list.ToList(); }
注意事项
- 此方式没有编译时类型校验,调用时若写错属性名,只会在运行时抛出错误。
- 若你的查询是EF的
IQueryable,直接返回会延迟执行,调用方遍历数据时才会访问数据库;需要立即获取数据的话,记得加上.ToList()。
2. 返回IEnumerable<object>(不推荐)
你也可以返回IEnumerable<object>,但调用时必须通过反射或类型转换访问属性,操作繁琐且易出错,示例如下:
public IEnumerable<object> GetTheList() { // 同上述LINQ查询代码 return list.ToList(); }
调用时需用反射获取属性:
foreach (var item in GetTheList()) { var transactionId = item.GetType().GetProperty("TransactionId").GetValue(item); // 其他属性需重复类似操作 }
补充说明
虽然以上方案能满足“无需定义新类型”的需求,但如果项目对类型安全有要求,**创建一个明确的DTO类(数据传输对象)**会更稳妥——只需定义一个包含所有所需属性的类,将匿名类型替换为该类的实例,就能获得编译时校验和更好的可读性。
内容的提问来源于stack exchange,提问作者Musaffar Patel
相关产品推荐
相关产品推荐

