2012-11-13 72 views
6

對它們進行排序我有實體的像這樣的第一列表:加入兩個不同類型的列表和按日期

public partial class Networking :EntityBase 
{ 

    public virtual int NetWorkingId 
    { 
     get; 
     set; 
    } 

    public virtual string NetWorkingParam 
    { 
     get; 
     set; 
    } 

    public virtual System.DateTime NetWorkingDate 
    { 
     get; 
     set; 
    } 
} 

我有實體的這樣一個第二個列表:

public partial class PrivateNetwork :EntityBase 
{ 
    public virtual int PrivateNetworkId 
    { 
     get; 
     set; 
    } 

    public virtual int ContaId 
    { 
     get { return _contaId; } 
     set 
     { 
      if (_contaId != value) 
      { 
       if (Contact != null && Contact.ContaId != value) 
       { 
        Contact = null; 
       } 
       _contaId = value; 
      } 
     } 
    } 

    public virtual Nullable<System.DateTime> DateCreation 
    { 
     get; 
     set; 
    } 
} 

我想要收集這兩個列表並按日期排序所有元素。

這可能嗎?

+0

你嘗試過什麼嗎? Linq的聯盟加入OrderBy可能會有所幫助... –

+0

是的,我嘗試過聯盟,但問題是如何對它們進行排序,因爲它們沒有相同的字段 – kbaccouche

+0

您可以選擇一個普通的匿名對象 –

回答

5

這個問題很容易通過使用多態性來解決;對這兩個類使用通用的基類或接口,它們具有要排序的DateTime屬性。

例子:

public abstract class NetworkingBase : EntityBase 
{ 
    public DateTime DateToSortOn { get; set; } 
} 

public interface INetworking 
{ 
    public DateTime DateToSortOn { get; set; } 
} 

然後讓你的類從NetworkingBase派生或實現INetworking

public partial class Networking : NetworkingBase 
{ 
    ... 
} 

public partial class PrivateNetwork : NetworkingBase 
{ 
    ... 
} 

public partial class Networking : EntityBase, INetworking 
{ 
    ... 
} 

public partial class PrivateNetwork : EntityBase, INetworking 
{ 
    ... 
} 

對結果集合執行LINQ UnionConcat,然後執行OrderBy

+5

這不是真的(共同的基礎*是必需的*);可以創建「聯合」對象 - 匿名或命名 - 然後可以對其進行排序/存儲。不需要共同基地。 – 2012-11-13 08:22:59

+0

@pst那麼你最終會得到一個匿名對象列表? – khellang

+0

我假設他有更多的基於EntityBase的實體。也許這個日期與這些類別無關。 –

5

你可以做到這一點,雖然不是很漂亮,和你結束了一個IEnumerable<object>所以你必須檢查每個項目的類型,然後才能使用它:

IEnumerable<object> sorted = myNetworkingList 
    .Concat<object>(myPrivateNetworkList) 
    .OrderBy(n => n is Networking 
       ? (DateTime?)((Networking)n).NetWorkingDate 
       : ((PrivateNetwork)n).DateCreation); 

foreach (object either in sorted) 
{ 
    if (either is Networking) 
     // Networking; do something 
    else 
     // PrivateNetwork; do something else 
} 
+0

-1:這是一個醜陋的解決方案,最好用多態性解決問題。當添加第三個'CafeWifiNetwork'類型時,除了最初的開發者(_famously faulty_)內存外,沒有什麼可以說這個linq和foreach循環需要改變。使用@khellang建議的任何方法,編譯器都會強制您正確編寫代碼。它會工作,但它不會通過任何代碼審查我會參加。 –

+0

@Binary這兩個類之間沒有共同之處 - 日期屬性甚至不是同一類型,更不用說同名 - 所以創建一個通用接口並不是真正的多態,它只是隱藏了一個討厭的操作(對列表進行排序不相關的對象)放在類本身中,而不是放在結果被消耗的代碼中。當它與網絡無關時,我尤其不會將它命名爲「INetworking」;它更像是'IArbitraryObejctThatHasANullableDateTimeProperty'。 – Rawling

+0

我衷心不同意。提交者想要合併列表並對它們進行排序有一些原因,所以在某種程度上在概念上**它們是相同的事物**。日期是「不同類型」的論點是虛假的,「DateTime?」涵蓋了兩者。最後,只有一個成員擁有'INetworkingCreatedDate'接口絕對沒有錯。即使你只是'在課堂上隱藏了一個討厭的操作',那麼在編譯器**強制執行關係的地方會更好_隱藏**,而不是散佈在代碼庫中的各種_難以找到的地方。 –

1

創建具有日期的接口並在兩個班中實施。之後,排序很容易。

public interface INetwork 
{ 
    DateTime? Date { get; } 
} 

public partial class Networking :EntityBase, INetwork 
{ 
    public DateTime? Date 
    { 
     get { return NetWorkingDate; } 
    } 
} 

public partial class PrivateNetwork :EntityBase, INetwork 
{ 
    public DateTime? Date 
    { 
     get { return DateCreation; } 
    } 
} 

var commonList = new List<INetwork>(); 
// Add instances of PrivateNetwork and Networking to the list 

var orderedByDate = commonList.OrderBy(n => n.Date); 
2

以前我應該問的是。 。 。

在排序後你想要做什麼?

答案可能會對潛在解決方案產生重大影響。

如果答案與類似,我需要顯示日期列表,其中您只需按順序排列日期。如果是這樣,那麼你不需要合併這兩個列表,你可以得到一系列僅僅有序的日期,並使用例如

var orderedDates = networks.Select(n => n.NetworkingDate) 
        .Union(privateNetworks.Select(n => n.DateCreation)) 
        .OrderBy(date => date); 

如果答案是我需要顯示的顯示鏈接到該對象的ID日期的鏈接列表,以及東西可供識別對象的類型,那麼你就可以逃脫的東西很像上面那樣,使用Anonymous對象。

var orderedDates = networks.Select(n => new {Date = n.NetworkingDate, Id = n.NetWorkingId, NetworkType = n.GetType().Name}) 
        .Union(privateNetworks.Select(n => new {Date = n.DateCreation, Id = n.PrivateNetWorkingId, NetworkType = n.GetType().Name})) 
        .OrderBy(n => n.Date); 

但是,如果答案是我需要發送關機()命令將10個最早的網絡然後你真的需要一個多態的解決方案,那就是你有一個單一的類型,你可以調用Shutdown()方法,該方法將解析爲您正在使用的類型的特定Shutdown()方法。

多態解決方案僅使用用戶是否khellang's answer不爲你

工作從一個評論對另一個答案

@BinaryWorrier我選擇了這個答案,因爲我已經在 記錄數據庫,所以如果我選擇添加一個新界面,在添加界面之前,我將如何處理 以及已經存儲的記錄?

我很難相信,你的ORM不會讓你的界面添加到實體類,而不是 - 不知何故 - 紀念該接口和/或它的成員,以便他們在ORM忽略。

但是,假設您不能添加新的接口或基類,您仍然可以以多態方式執行此操作。

添加界面,添加一個類實現該接口對於每個網絡分類(Abstractor類)的,則變換網絡類成Abstractor類,將它們添加到List<INetwork>和排序該列表。

public interface INetwork 
{ 
    DateTime? Date { get; } 
} 

public class PrivateNetworkAbstractor 
    :INetwork 
{ 
    private PrivateNetwork network; 
    public PrivateNetworkAbstractor(PrivateNetwork network) 
    { 
     this.network = network; 
    } 
    public DateTime? Date 
    { 
     get { return network.DateCreation; } 
    } 
} 

public class NetworkingAbstractor 
    : INetwork 
{ 
    private Networking networking; 
    public NetworkingAbstractor(Networking networking) 
    { 
     this.networking = networking; 
    } 
    public DateTime? Date 
    { 
     get { return networking.NetWorkingDate; } 
    } 
} 
... 

public IEnumerable<INetwork> MergenSort(IEnumerable<Networking> generalNetWorks, IEnumerable<PrivateNetwork> privateNetWorks) 
{ 
    return generalNetWorks.Select(n => new NetworkingAbstractor(n)).Cast<INetwork>() 
    .Union(privateNetWorks.Select(n => new PrivateNetworkAbstractor(n)).Cast<INetwork>()) 
    .OrderBy(n=> n.Date); 
} 
+0

+1爲幾乎裝飾模式:) – khellang

+0

@KristianHellang:曾經有一段時間我知道模式書向後,但我沒有打開它多年,現在我記得技術,但忘記了模式的名稱,或忘記我將這項技術學習爲一種模式。男孩我希望我的大腦能像20年前那樣工作。 。 。 –

0

首先溶液使用匿名類型

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Example1 
{ 
    class Program 
    { 
     class Human 
     { 
      public string Name { get; set; } 
      public string Hobby { get; set; } 
      public DateTime DateOfBirth { get; set; } 
     } 
     class Animal 
     { 
      public string Name { get; set; } 
      public string FavouriteFood { get; set; } 
      public DateTime DateOfBirth { get; set; } 
     } 

     static void Main(string[] args) 
     { 
      var humans = new List<Human> 
      { 
       new Human 
       { 
        Name = "Kate", 
        Hobby = "Fitness", 
        DateOfBirth = DateTime.Now.AddYears(-27), 
       }, 
       new Human 
       { 
        Name = "John", 
        Hobby = "Cars", 
        DateOfBirth = DateTime.Now.AddYears(-32), 
       }, 
      }; 

      var animals = new List<Animal> 
      { 
       new Animal 
       { 
        Name = "Fluffy", 
        FavouriteFood = "Grain", 
        DateOfBirth = DateTime.Now.AddYears(-2), 
       }, 
       new Animal 
       { 
        Name = "Bongo", 
        FavouriteFood = "Beef", 
        DateOfBirth = DateTime.Now.AddYears(-6), 
       }, 
      }; 

      var customCollection = (from human in humans 
            select new 
             { 
              Name = human.Name, 
              Date = human.DateOfBirth, 
             } 
             ).Union(from animal in animals 
               select new 
                { 
                 Name = animal.Name, 
                 Date = animal.DateOfBirth, 
                }).OrderBy(x => x.Date); 


      foreach (dynamic customItem in customCollection) 
       Console.WriteLine(String.Format("Date: {0}, Name: {1}",  customItem.Date, customItem.Name)); 

      Console.Read(); 
     } 
    } 
} 

或不匿名類型(創建CustomClass):

... 
class CustomClass 
     { 
      public string Name { get; set; } 
      public DateTime Date { get; set; } 
     } 
... 
var customCollection = (from human in humans 
            select new CustomClass 
             { 
              Name = human.Name, 
              Date = human.DateOfBirth, 
             } 
             ).Union(from animal in animals 
               select new CustomClass 
                { 
                 Name = animal.Name, 
                 Date = animal.DateOfBirth, 
                }).OrderBy(x => x.Date); 


      foreach (CustomClass customItem in customCollection) 
       Console.WriteLine(String.Format("Date: {0}, Name: {1}", customItem.Date, customItem.Name)); 

... 
0

我簡單地加入鹼類並分配它作爲兩者的父列表的類。然後簡單的工會。它訣竅

相關問題