简而言之,我知道问题出在哪里,就是这个...
...我也知道默认情况下这是不可能的。
我的问题(见下文)在这里,我如何才能做到这一点(即使我必须动态调用例如Roslyn编译器以生成一个全新的具体程序集)?
有什么办法可以使以下查询在C#中成为可能?
所以假设我有以下示例数据...
var data = @"
{
""$type"":""System.Dynamic.ExpandoObject, System.Core"",
""Items"":[
{ ""$type"":""System.Dynamic.ExpandoObject, System.Core"", ""Ref"":1, ""BuyerRef"":1, ""SupplierRef"":2, ""FaceValue"":1.34 },
{ ""$type"":""System.Dynamic.ExpandoObject, System.Core"", ""Ref"":1, ""BuyerRef"":1, ""SupplierRef"":2, ""FaceValue"":2.12 },
{ ""$type"":""System.Dynamic.ExpandoObject, System.Core"", ""Ref"":2, ""BuyerRef"":1, ""SupplierRef"":3, ""FaceValue"":100.0 },
{ ""$type"":""System.Dynamic.ExpandoObject, System.Core"", ""Ref"":3, ""BuyerRef"":1, ""SupplierRef"":2, ""FaceValue"":1.0 },
{ ""$type"":""System.Dynamic.ExpandoObject, System.Core"", ""Ref"":4, ""BuyerRef"":3, ""SupplierRef"":2, ""FaceValue"":1.0 },
{ ""$type"":""System.Dynamic.ExpandoObject, System.Core"", ""Ref"":5, ""BuyerRef"":4, ""SupplierRef"":1, ""FaceValue"":1.0 },
{ ""$type"":""System.Dynamic.ExpandoObject, System.Core"", ""Ref"":5, ""BuyerRef"":4, ""SupplierRef"":1, ""FaceValue"":1.0 }
],
""Companies"":[
{ ""CompanyId"":1, ""CompanyName"":""Sample Company 1"" },
{ ""CompanyId"":2, ""CompanyName"":""Sample company 2"" },
{ ""CompanyId"":3, ""CompanyName"":""ACME"" },
{ ""CompanyId"":4, ""CompanyName"":""HSBC Bank UK"" },
{ ""CompanyId"":5, ""CompanyName"":""Basic Buyer UK Ltd"" },
{ ""CompanyId"":6, ""CompanyName"":""Test Global US-CA"" },
{ ""CompanyId"":7, ""CompanyName"":""Test Global US-TX"" },
{ ""CompanyId"":8, ""CompanyName"":""Test Global US-NH"" },
{ ""CompanyId"":9, ""CompanyName"":""Test Global UK"" },
{ ""CompanyId"":10, ""CompanyName"":""Test Global FR"" }
]
}
";
然后我使用Newtonsofts JsonConvert解析...
object source = JsonConvert.DeserializeObject<ExpandoObject>(data);
现在我想做类似...
var result = source.Items.Select(item => new
{
Ref = item.Ref,
FaceValue = item.FaceValue,
BuyerId = item.BuyerRef,
Buyer = Companies.Where(company => item.BuyerRef == company.CompanyId).Select(company => company).FirstOrDefault(),
SupplierId = item.SupplierRef,
Supplier = Companies.Where(company => item.SupplierRef == company.Ref).Select(company => company).FirstOrDefault()
})
.ToArray()
.GroupBy(i => new { i.Ref, i.Buyer, i.Supplier })
.Select(group => new
{
Ref = group.Key.Ref,
BuyerId = group.Key.Buyer.Ref,
Buyer = group.Key.Buyer,
SupplierId = group.Key.Supplier.Ref,
Supplier = group.Key.Supplier,
Lines = group.Select(i => new { Ref = i.Ref, FaceValue = i.FaceValue }).ToArray(),
FaceValue = group.Sum(i => i.FaceValue)
})
.ToArray();
...当然,问题在于数据是完全动态的,而LINQ不能用于动态对象。
可以做的假设...
这在C#中完全可行吗?
答案 0 :(得分:2)
好的,我已经可以处理您的样本数据,但是我不得不更改大量代码:
首先,您需要告诉编译器将source.Items
和source.Companies
视为IEnumerable<dynamic>
值。只需将它们提取到局部变量并使用隐式转换就足够了:
IEnumerable<dynamic> items = source.Items;
IEnumerable<dynamic> companies = source.Companies;
接下来,由于您假设公司条目具有Ref
属性,因此您的查询在各个地方都被打乱了-它们没有,只有CompanyId
。这是我担心您的假设,即“查询已验证并检查,并且肯定会根据给定的数据进行工作”-如果您提供的示例不是这种情况,您将如何确保确实如此在现实中?
为简单起见,我还将您的...Where(...).Select(company => company).FirstOrDefault()
部分转换为.FirstOrDefault(...)
。此外,要使Sum
正常工作,您实际上需要确保每个元素都具有相同的类型-强制转换对此最简单。
最后,我删除了中间的ToArray
调用,该调用没有什么特别的用处,并使用了投影初始化方法,其中匿名类型中的属性名称是您要从中提取属性的名称。 (您已经在GroupBy
中进行了此操作-我要做的更多。)
将代码保留为:
dynamic source = JsonConvert.DeserializeObject<ExpandoObject>(data);
IEnumerable<dynamic> items = source.Items;
IEnumerable<dynamic> companies = source.Companies;
var result = items
.Select(item => new
{
item.Ref,
item.FaceValue,
BuyerId = item.BuyerRef,
Buyer = companies.FirstOrDefault(company => item.BuyerRef == company.CompanyId),
SupplierId = item.SupplierRef,
Supplier = companies.FirstOrDefault(company => item.SupplierRef == company.CompanyId)
})
.GroupBy(i => new { i.Ref, i.Buyer, i.Supplier })
.Select(group => new
{
group.Key.Ref,
BuyerId = group.Key.Buyer.CompanyId,
group.Key.Buyer,
SupplierId = group.Key.Supplier.CompanyId,
group.Key.Supplier,
Lines = group.Select(i => new { i.Ref, i.FaceValue }).ToArray(),
FaceValue = group.Sum(i => (decimal) i.FaceValue)
})
.ToArray();
foreach (var item in result)
{
Console.WriteLine(item);
}
至少可以打印出值-我不知道它们是否是您想要的值,但希望它们是...