在inheritance的数组LINQ中添加元素

关注上一个问题,这是我的一般类结构..

LINQ基于类型和Summate它们的值组合列表中的元素

我试图使用各自的.Add方法组合项目,但由于entity framework的考虑,我只能处理基类型(非接口)。

using System.Linq; using System.Collections.Generic; interface Item { T Add(T item); } abstract class Item { public ItemType Type; public int Value; } class SubItemOne : Item, Item { public int Additional { get; set; } public SubItemOne Add(SubItemOne item) { // .. } } class SubItemTwo : Item, Item { public int MoreData { get; set; } public int OtherData { get; set; } public SubItemTwo Add(SubItemTwo item) { // ... } } class SubItemThree : Item, Item { public int StillOtherData { get; set; } public int SecondaryData { get; set; } public int TertiaryData { get; set; } public SubItemThree Add(SubItemThree item) { // ... } } class ItemType { public string Name; } class Test { public static void Main() { List types = new List(); types.Add(new ItemType { Name = "Type1" }); types.Add(new ItemType { Name = "Type2" }); types.Add(new ItemType { Name = "Type3" }); List items = new List(); for (int i = 0; i  t.Name == "Type1"), Additional = i }); } for (int i = 0; i  t.Name == "Type2"), MoreData = 10, OtherData = i + 10 }); } for (int i = 0; i  t.Name == "Type3"), SecondaryData = 1000, StillOtherData = 1874, TertiaryData = i * 10 }); } List combined = new List(); // create a list with 3 items, one of each 'type', with the sum of the total values of that type. // types included are not always known at runtime. // I am trying to invoke the .Add Method on the items so that they can be collatted together. However // they all return as the base type. } } 

问题是你将不得不在更高级别处理接口,因此通常不能这样做(即,使用generics类型参数)。 您将不得不定义这些类实现的非generics接口(即使它是当前通用接口的补充),以便执行您所需的操作。 在分配兼容性方面, ItemItem不再相关,而stringDateTime

如果你必须这样做,那么你将不得不使用reflection。 这应该是诀窍:

 Dictionary sum = new Dictionary(); foreach (var item in items) { Item currSum; if (sum.TryGetValue(item.Type, out currSum)) { sum[item.Type] = (Item)item.GetType().GetInterfaces().Single( i => i.Name == "Item").GetMethod("Add") .Invoke(currSum, new object[] { item }); } else { sum.Add(item.Type, item); } } List combined = sum.Values.ToList(); 

详细说明问题是如何解决的。 我要感谢那些协助这个答案的人,(我还要感谢jarret,从我之前涉及linq查询的问题)来帮助我完全得到解决方案。

虽然我不喜欢在The Resources文件夹中盯着我的Microsoft.CSharp.dll库(我知道你在那里,即使我崩溃了你!我也没有尝试否认它!)

总而言之,LINQ让我感到惊讶,但令我感到震惊和震惊的是, dynamic更有效。 为了测试,我在三个派生类“Add”方法中的每一个中NotImplementedException了一个“ NotImplementedException ”并运行整个执行,当编译器爆发以显示Exception时,它就在相应的类中。 在两种情况下都测试了这一点。

另外,这表明当涉及reflection的实现初始化时,参数实际上与名称不同。 我测试了相同的创建接口IItemIItem并得到了相同的结果。 (另外,当IItem是实现的接口时,IItem`1也产生相同的结果)。

每次我从Stackoverflow得到答案时,它都会让我感到惊讶和惊讶,无论我多么认为我知道,有这么多人知道更多,但不仅如此,他们正在浏览相同的资源网站我我愿意回答这些耗费时间和资源的问题。 再次感谢所有帮助过的人!

使用亚当罗宾逊的方法,我从这个角度来看待它。

  var grouped = items.GroupBy(i => i.Name); grouped.ForEach(x => { x.ForEach(e => { // results handled here // assumes that all objects inheriting "Item" implement IItem, which contracts "Add" method. e.GetType().GetInterfaces().First(i => i.Name == "IItem").GetMethod("Add").Invoke(e, new object[] { e }); }); }); 

使用arootbeer的答案。

  var grouped = items.GroupBy(i => i.Name); grouped.ForEach(x => { x.ForEach(e => { // results handled here ((dynamic)e).Add((dynamic)e); }); });